How to get a tree in HTML using pure CSS

2019-01-22 04:25发布

问题:

I am trying to follow this tutorial and here's my code so far.

The end of the tutorial shows that the last nodes in a branch won't have any vertical bars after it. But I couldn't get it working that way!. Any ideas if I am doing something wrong, or maybe the tutorial is missing something!

I tried even the :last-child pseudo class as shown in the tutorial, but got the same result.

回答1:

Here's a try using only pseudo-elements and borders:

ul, li{     
    position: relative;    
}

/* chop off overflowing lines */
ul{
    overflow: hidden;
}

li::before, li::after{
    content: '';
    position: absolute;
    left: 0;
}

/* horizontal line on inner list items */
li::before{
    border-top: 1px solid #333;
    top: 10px;
    width: 10px;
    height: 0;
}

/* vertical line on list items */    
li::after{
    border-left: 1px solid #333;
    height: 100%;
    width: 0px;
    top: -10px;
}

/* lower line on list items from the first level 
   because they don't have parents */
.tree > li::after{
    top: 10px;
}

/* hide line from the last of the first level list items */
.tree > li:last-child::after{
    display:none;
}

demo (edited)



回答2:

Sadly, the pseudo-class is defined in the upcoming CSS3 specification and at the moment few web browsers support it.

It's written at the end of the tutorial. Maybe that's the reason it's not working.



回答3:

I believe I've fixed it: https://github.com/gurjeet/CSSTree/pull/1

I modified the CSS to remove the background and changed margin to padding.

ul.tree, ul.tree ul {
    list-style-type: none;
    margin:0;
    padding:0;
}

ul.tree ul {
    padding-left: 1em;
    background:  url(vline.png) repeat-y;
}

ul.tree li {
    margin:0;
    padding: 0 1.2em;
    line-height: 20px;
    background: url(node.png) no-repeat;
    color: #369;
    font-weight: bold;
}

/* The #fff color background is to hide the previous background image*/
ul.tree li.last {
    background: #fff url(lastnode.png) no-repeat;
}

ul.tree ul:last-child {
    background: none;
}


回答4:

Thank you guys, helpful answers which made me read some more, and finally I read this article and removed all dependency on JavaScript, and used the nth-last-of-type pseudo-selector to apply the special background to the last li items in a list (ignoring the ul that comes after the last li).

The final code is here. I am going to accept my own answer, unless someone points out some problem with it. (I don't think compatibility with older browsers matters to me at this stage.)

Thanks to @Aram for the answer. @OneTrickPony, your answer went over the head of this noob :) I am sure it does the right thing, but it's a bit too complicated for me.

<style type="text/css">
/* ul[class=tree] and every ul under it loses all alignment, and bullet
 * style.
 */
ul.tree, ul.tree ul {
    list-style-type: none;
    margin:0;
    padding:0;
}

/* Every ul under ul[class=tree] gets an indent of 1em, and a background
 * image (vertical line) applied to all nodes under it (repeat-y)
 */
ul.tree ul {
    padding-left: 1em;
    background:  url(vline.png) repeat-y;
}

/* ... except the last ul child in every ul; so no vertical lines for
 * the children of the last ul
  */
ul.tree ul:last-child {
    background: none;
}

/* Every li under ul[class=tree]
 *  - gets styling to make it bold and blue, and indented.
 *  - gets a background image (tilted T), to denote that its a node
 *  - sets height to match the height of background image
 */
ul.tree li {
    margin:0;
    padding: 0 1.2em;
    background: url(node.png) no-repeat;
    line-height: 20px;
    color: #369;
    font-weight: bold;
}

/*  The last li gets a different background image to denote it as the
 *  end of branch
 */
ul.tree li:nth-last-of-type(1) {
    background: url(lastnode.png) no-repeat;
}