CSS3 Treeview. No JavaScript.

Try Semtex – the new HTML5, CSS3 and JavaScript UI framework!

Can you believe that the treeview on the image below does not use any JavaScript, but relies only on CSS3?

Go to the live example

CSS3 Treeview. No JavaScript.

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:

<div class="css-treeview">
    <ul></ul>
</div>

… 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:

<li><a href="./">item</a></li>
<li><a href="./">item</a></li>

Expandable (clickable) submenu item:

<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>

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:

.css-treeview input + label + ul
{
    display: none;
}

Selected checkbox:

.css-treeview input:checked + label + ul
{
    display: block;
}

For aesthetic purposes we hide the checkboxes like this:

.css-treeview input
{
    position: absolute;
    opacity: 0;
}

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:

.css-treeview input:checked:not(:disabled) + label + ul
{
    display: block;
}

The visual representation of the disabled items can be accomplished by changing the opacity and the cursor of the label element:

.css-treeview input:disabled + label
{
    cursor: default; /* or no-drop */
    opacity: .6;
}

Finally, for the +/- buttons on the left, we can use generated content with the :before pseudo element:

.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;
}

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:

li a[href$=".js"]
{
    background: url("js.png") no-repeat center;
}

li a[href$=".css"]
{
    background: url("css.png") no-repeat center;
}

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

About these ads

79 comments

  1. Works with Google Chrome v18 but not with v19(current) or v20(beta) – the branches do not expand/collapse when clicked with these chrome versions on Windows 7/Server 2008 R2. Google Chrome auto-updated a day or two ago to v19.0.1084.46 and since then it has no longer worked. Safari and iOS confirmed working OK.

  2. …just as a side note, you mention using CSS3 transitions. The most obvious application for this would be to smoothly transition when branches are expanded/collapsed. I’m not sure how this can be achieved when switching between display: none and display: block in CSS as changing the display element seems to break transitions. Any ideas?

  3. Never mind, I think I found the right selector to get the effect I wanted…

    .css-treeview input:checked ~ label
    {
    background-position: 18px -46px; /* in my case I added a fourth icon that is the open folder to the icons.png */
    }

    1. Thanks for the comment. However, I just checked, ane it is working perfectly in IE10 standards compliance mode. I did not check in quirks mode, because I am not interested non-standards compliant mode.

  4. Is that possible to have collapse all and expand all buttons on top and implement the same like you did for single expand. I could not find any in the internet. Do you have any idea??

  5. I found the answer for my problem… I use disabled and checked properties from input tag and it worked.

  6. My requirement needed only expand/collapse arrows but not the folder, I edited the icons.png sprite and removed the folder but I was left with a space between the arrow and the text (the space for the folder icon as blank). I tried editing the css but it is not working.. can you help me out?

      1. Hi, I implemented this awesome tree on IE 9 and other browsers and it worked,but now my client wants to use it in IE8,can you please give the javascript solution you mentioned to implement this in IE8?Its very urgent and necessary.
        Thanks

  7. awesome! thank you very much for the post.

    p.s. is there a way of of making them expand/collapse smoother? there’s no way to apply CSS transition to “display” property :)

    1. Hey there! Thank you very much for the comment. Unfortunately you cannot apply CSS3 transitions to the display property, however you can experiment with opacity: 0-1 and position: absolute.

    1. It does not appear, because on line 47 you have:

      .css-treeview input ~ ul
      {
      display: none;
      }

      You should set explicitly what you would like to do with inputs of type text like that:

      input[type="text"]
      {
      /* css */
      }

    1. Sorry, my mistake. Here’s how:

    2. Lorem
    3. .css-treeview input[type="text"]
      {
      position: static;
      opacity: 1;
      }

      I’ve used position: absolute and opacity: 0 instead of display: none; to hide the checkboxes in order to circumvent a behaviour in Internet Explorer. This is why you should set position: static and opacity: 1 to the text inputs in order to make them visible.

  8. Thanks for the reply It was really helpful.

    One issue:
    If you see the list the one with disabled=”disabled”. I have a scenario in which I want to keep my attribute disabled=”disabled”, However I want the list should not be collapsed.

    Is it possible to make disable list Open by Default ?

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s