I am trying to create a tree with indentations in pure CSS. I have been trying using something like:
ul.tree ul {
padding-left: 5px;
}
Ho
This CSS makes the link inside a nested li
have a padding-left
of 30px
, and I add another nested li
link have padding-left: 60px
.
ul.tree li ul li a {
padding-left: 30px;
}
ul.tree li ul li ul li a {
padding-left: 60px;
}
http://jsfiddle.net/7u87c/5/
No extra markup and use of icon image.
Pretty simple and dynamic based on the content.
Sample HTML:
<ul class="tree">
<li><span>public</span></li>
<li><span>server.js</span></li>
<li>
<span>server</span>
<ul>
<li><span>webfs</span></li>
</ul>
</li>
<li><span>specs</span></li>
<li>
<span>src</span>
<ul>
<li>
<span>core</span>
<ul>
<li><span>CellAddress.js</span></li>
</ul>
</li>
</ul>
</li>
</ul>
CSS:
ul.tree {
border-top: 1px solid grey;
}
ul.tree, ul.tree ul {
padding: 0;
margin: 0;
list-style: none;
}
ul span {
display: block;
padding-left: 25px;
border-bottom: 1px solid #666;
height: 25px;
line-height: 25px;
background: url("http://lorempixel.com/10/8/") no-repeat scroll 5px 8px transparent;
}
ul ul span {
padding-left: 35px;
background-position: 15px 8px;
}
ul ul ul span {
padding-left: 45px;
background-position: 25px 8px;
}
Please see example
Note: You can convert the spans
into a
tags
For lists with unknown depths, I've used an absolutely positioned element for separating lines. It adds a little extra markup, but seems to work.
div.separator {
position:absolute;
left:0px;
right:0px;
border-top:1px solid lightgray;
}
<ul class="tree">
<li><a>Item1</a><div class="separator"></div></li>
<li><a>Item2</a><div class="separator"></div>
<ul>
<li><a>Item3</a><div class="separator"></div></li>
<li><a>Item4</a><div class="separator"></div></li>
<li><a>Item5</a><div class="separator"></div>
<ul>
<li><a>Item6</a><div class="separator"></div></li>
</ul>
</li>
</ul>
</li>
</ul>
http://jsfiddle.net/7u87c/20/
UPDATED: Tweaked to accommodate hover
No extra HTML needed, no having to limit depth because of css selector chaining, as it supports any number of levels deep without having to adjust your css at all for those levels (no keeping track of "padding" to set on the next level deep).
This works well with only a two minor limitations (which I don't believe will factor into affecting you).
See fiddle demo.
Add a position: relative
to your ul.tree
, but keep all the child elements the default static
position. Then change/add the following css:
ul.tree a {
display: block;
height:30px;
line-height: 30px;
padding-left: 15px;
}
/* this is making our bottom border, but sizing off the .tree ul width */
ul.tree a:before {
content: '';
height: 30px; /* match your <a> height */
position: absolute;
left: 0;
right: 0;
z-index: -1;
border-bottom-width: 1px;
border-bottom-color: lightgray;
border-bottom-style: solid;
}
ul.tree a + ul {
padding-left: 15px; /* this is your spacing for each level */
}
ul.tree a:hover:before {
background-color: #DDDDDD;
}
The limitations are that no child elements can have a position set and we are using a pseudo-element (which means it cannot be used for some other feature, but that is probably not an issue either).