We recently published a great tutorial which built Orman Clark's vertical navigation menu into a flexible, jQuery powered accordion. It's actually possible to get the whole thing working without leaning on jQuery at all, and is the perfect chance to play with the CSS :target selector.

So… How?

We're going to forget jQuery and instead use the CSS :target pseudo selector to make our accordion menu expand and contract.

The :target Pseudo Selector

You'll no doubt be familiar with URLs that look like this: http://www.w3.org/TR/selectors/#target-pseudo. It finishes off with a # sign and an element id, which is used to take the browser directly to that element. This particular url is the perfect example - it takes you to the heading with an id of #target-pseudo (feel free to go and read up).

When stitched onto the end of a url, this id is known as a fragment identifier. It's not just used to take the browser to a location on the page, it can also be used via CSS to identify the element in question.

In short; we use :target to select and manipulate the element in the fragment identifier.

Step 2: Can I See Some Identification?

As mentioned above, the :target selector will point at any element which is referred to in the fragment identifier. We therefore need to make sure our primary list items all have unique IDs, and that the anchors within them have corresponding links:

Now, when you click on the links, you'll see a fragment identifier appear in the url:

Step 3: Collapse

Currently, having removed all the jQuery bits and bobs, the accordion will be fully expanded. We need its initial state to be collapsed, so that we can reveal each sub section when the links are clicked.

Head over to the existing CSS file, we're going to add some rules to the bottom:

We're pointing to our submenus here; any direct descendant of the .menu list items. We're saying that their initial height is 0, and that any overflow is hidden to prevent content pushing its way into view. We now have the whole thing collapsed. And that's how it will remain unless we do something about it..

Step 4: And Expand

We want each submenu to expand, but only when we've clicked on its parent link. Let's use :target to select them:

.menu > li:target > ul {
height: auto;
}

Put simply, this says: "See that li which is mentioned in the url? Well, change the height of the ul within it to auto". Once you click somewhere else and the id no longer appears in the url, the submenu collapses again. Try it!

Step 5: Embellishments

Visually, there are a couple of things left to do. The active state is no longer assigned by jQuery, so we need to make sure our :target list items are blue. These no longer exist:

Step 6: Transitions

I know. You're yelling at the screen "What about the smooth transitions?!" I'm afraid you're going to be disappointed. Unless we specify a definite height for the submenus, we can't use CSS transitions to smoothly expand and collapse our accordion. Transitions won't play nicely with height: auto. Of course, you could specify a definite height:

What we've done is set the default opacity of the submenu to 0; not only does it have a height of 0, it's now transparent too. We then also set the transitions on the default state. On the hover state, it still snaps wide open, but then the contents fade into view. A bit easier on the eye.

Step 7: Legacy Browsers

Another issue is the fact that :target isn't recognized by older browsers (Internet Explorer 8 and below), so our collapsed menu is rendered useless in those browsers. Let's apply a couple of alternative methods, which will at least make the navigation accessible.

Again, check out the demo. Not exactly what we were after, but at least it's a backwards compatible, accessible navigation.

Conclusion

Given the choice, you'll probably still opt for the jQuery approach; it's equally accepted in all browsers (as long as JavaScript is enabled) and the effect is smoother. Still, if you weren't aware of the :target selector, this Quick Tip will hopefully have given you an insight into more CSS potential.