Today I’m going to show you a really easy and absolutely JavaScript-less solution for creating multi-level treeviews with minimal markup and with the power of CSS3. Basically what we need is a simple list:
[sourcecode language=”html”]
<div class="css-treeview">
<ul></ul>
</div>
[/sourcecode]
… With any number of nested items and subtrees. Each item that is going to be a container of a subtree should be supplied with a label and a checkbox.
Normal (non-clickable) item:
[sourcecode language=”html”]
<li><a href="./">item</a></li>
<li><a href="./">item</a></li>
[/sourcecode]
Expandable (clickable) submenu item:
[sourcecode language=”html”]
<li><input type="checkbox" id="item-0" /><label for="item-0">folder</label>
<ul>
<li><input type="checkbox" id="item-0-0" /><label for="item-0-0">folder</label>
<ul>
<li><input type="checkbox" id="item-0-0-0" /><label for="item-0-0-0">folder</label>
<ul>
<li><a href="./">item</a></li>
<li><a href="./">item</a></li>
<li><a href="./">item</a></li>
<li><a href="./">item</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
[/sourcecode]
Making it work is pretty simple and straightforward. All we need is to query the normal and :checked states of the checkboxes and set the adjacent <ul /> element to visible or hidden in the stylesheet:
Unchecked checkbox:
[sourcecode language=”css”]
.css-treeview input + label + ul
{
display: none;
}
[/sourcecode]
Selected checkbox:
[sourcecode language=”css”]
.css-treeview input:checked + label + ul
{
display: block;
}
[/sourcecode]
For aesthetic purposes we hide the checkboxes like this:
[sourcecode language=”css”]
.css-treeview input
{
position: absolute;
opacity: 0;
}
[/sourcecode]
It is recommended to hide the checkbox with position/opacity rather than with display: none, otherwise you will have problems with certain browsers.
If your treeview is going to contain disabled subtrees, you can utilize the :not() selector, so disabled items with submenus will not be clickable:
[sourcecode language=”css”]
.css-treeview input:checked:not(:disabled) + label + ul
{
display: block;
}
[/sourcecode]
The visual representation of the disabled items can be accomplished by changing the opacity and the cursor of the label element:
[sourcecode language=”css”]
.css-treeview input:disabled + label
{
cursor: default; /* or no-drop */
opacity: .6;
}
[/sourcecode]
Finally, for the +/- buttons on the left, we can use generated content with the :before pseudo element:
[sourcecode language=”css”]
.css-treeview label,
.css-treeview label::before
{
background: url("icons.png") no-repeat;
}
.css-treeview label::before
{
content: "";
width: 16px;
margin: 0 22px 0 0;
vertical-align: middle;
background-position: 0 -32px;
}
.css-treeview input:checked + label::before
{
background-position: 0 -16px;
}
[/sourcecode]
All of the icons that have been used in the example are in the icons.png sprite. The solution will work with any browser supporting the adjacent element selector (E + E) and the attribute selectors of CSS3. Do not forget that the values of the for/id attribute pairs for the label and checkbox elements should be unique, otherwise the treeview will not work. Tab/Spacebar navigation is supported natively. The demo is availble on this page, or you can download it straight away from this link.
Of course this is just the basic concept that you can use for inspiration. A few ideas that can bring you even further:
– By adding the disabled attribute to a checkbox in your markup, the nested subtree will become expanded by default.
– You can use the cool CSS3 transitions to achieve cool behaviors.
– You can use additional classes to display different “folder” items.
– You can use :hover in order to show the pluses and minuse only when the treeview is hovered.
– You can use an additional class name that will show the pluses and minuses only when applied.
– You can use the attribute selectors to display different icons for each normal item according to the extension in the href attribute, for example:
[sourcecode language=”css”]
li a[href$=".js"]
{
background: url("js.png") no-repeat center;
}
li a[href$=".css"]
{
background: url("css.png") no-repeat center;
}
[/sourcecode]
This solution works with all modern browsers and Internet Explorer 9+. If you are interested in purchasing a JavaScript enabler for IE8 for the CSS3 Treeview, please, click here.
View the demo and find more experiments here.
Related Posts
© 2006 - 2024 Martin Ivanov