Bernhold's random tech tips

Completely unintelligible techie babble that doesn't explain why it should be important to anyone in whatever way

Very simple pure CSS collapsible list without JavaScript

Lately, I stumbled upon this great article on The CSS Ninja. It shows a technique for pure CSS collapsible lists, without any JavaScript. It works for all modern browsers. With Internet Explorer 8 or older though, it's not possible with pure CSS. These browsers need to emulate CSS pseudo-classes by adding a small JavaScript fix to the page, which I demonstrate at the bottom of this article.

The code on CSS Ninja was a bit too sophisticated for me. It took some time until I realized what's the magic behind it. I dismantled the code and simplified it as much as possible to understand it better. Here's how my simple collapsible list looks:

    • Item 1
    • Item 2
    • Item 3
    • Item 1
    • Item 2
    • Item 3

Note the checkboxes next to the list items. They are used as a switch to show and hide the list contents. We need them because without JavaScript, there's no variable to keep track of the visibility status of our list items. Don't worry at this point, we will hide the checkboxes later. I just left them visible to show you how it works.

CSS code

.collapsibleList li > input + * {
 display: none;
}
 
.collapsibleList li > input:checked + * {
 display: block;
}

.collapsibleList li > input {
 display: none;
}

.collapsibleList label {
 cursor: pointer;
}

HTML code

<ul class="collapsibleList">
 <li>
  <label for="mylist-node1">Click to open list 1</label>
  <input type="checkbox" id="mylist-node1" />
  <ul>
   <li>Item 1</li>
   <li>Item 2</li>
   <li>Item 3</li>
  </ul>
 </li>
 <li>
  <label for="mylist-node2">Click to open list 2</label>
  <input type="checkbox" id="mylist-node2" />
  <ul>
   <li>Item 1</li>
   <li>Item 2</li>
   <li>Item 3</li>
  </ul>
 </li>
</ul>

Now that's simple, isn't it? Any list with the collapsibleList class will become a collapsible list. This is the complete code, you don't need anything else. Read on for a look behind the scenes.

How it works

The magic happens at the <label> and <input> tags. The clickable list items look like ordinary links, but they are actually form element labels paired with a checkbox. Because they have the same ID, they are linked to each other, and clicking on a label will automatically tick its corresponding checkbox.

Note that each label and checkbox have to be paired with an unique identifier, like so:

<label for="mylist-node1" />
<input type="checkbox" id="mylist-node1" />

Here, mylist-node1 is the ID used to connect the label to the checkbox. It doesn't matter how you name the ID pairs, they just have to be unique across the page. If you don't pair them with an ID, the checkbox won't be ticked when you click on the label, because there is no semantic relationship between them.

Collapsing the list

.collapsibleList li > input + * {
  display: none;
 }

This code initially collapses our list by setting the first element following each checkbox to be invisible. In our example, the first element after each input element is another list, but it could be anything.

Expanding the list

.collapsibleList li > input:checked + * {
  display: block;
}

This is where the magic happens. We use the checked CSS pseudo-class for matching any ticked checkbox within our collapsible list. If it's ticked, we set the element immediately following the checkbox (in our example it's another list) to be visible.

Hiding the checkboxes

Now what about those ugly checkboxes, how to make them disappear? Just set their display property to none:

.collapsibleList li > input {
 display: none;
}

Done! This is how our finished list looks like:

    • Item 1
    • Item 2
    • Item 3
    • Item 1
    • Item 2
    • Item 3

CSS fix for IE 8 and older

As mentioned, the collapsible list will work with all modern browsers. However, it won't work out of the box with IE 8 or older. These browsers need a JavaScript CSS selector fix like ie7-js. Add this fix to your page to make it work.

For IE 7 or older, you additionally have to modify the above CSS code for hiding the checkboxes, because display: none won't work. As a workaround, we simply position the checkboxes outside of the body:

.collapsibleList li > input {
 position: absolute;
 left: 0;
 margin-left: -999px;
}

This code is kind of a hack, but it provides the highest compatibility. It works for all modern browsers and Internet Explorer 6, 7 and 8.

src: bernholdtech.blogspot.de/2013 -- April 7, 2013