By Craig Buckler

How to Create a CSS3-Only Vertical Accordion Using the :target Selector

By Craig Buckler

We recently created a CSS3-Only tab control which used the powerful :target selector. One of the major benefits of CSS is that we can restyle HTML how we like; so we’re going to transform our mark-up into a vertical accordion.

View the demonstration page…

The solution works in IE9, Chrome, Firefox, Safari and Opera and doesn’t require JavaScript or images. It fails miserably in IE6, 7 and 8 so you could either use the selectivizr shim or hide the widget from those users and tell them to upgrade.


Our HTML5 code is identical to that used by the tab control. I’ve only changed the article class to “accordion” and renamed some of the IDs so it’s easier to understand what’s going on. There are also five sections since it looks a little better:

<article class="accordion">

	<section id="acc1">
		<h2><a href="#acc1">Title One</a></h2>
		<p>This content appears on page 1.</p>
	<section id="acc2">
		<h2><a href="#acc2">Title Two</a></h2>
		<p>This content appears on page 2.</p>
	<section id="acc3">
		<h2><a href="#acc3">Title Three</a></h2>
		<p>This content appears on page 3.</p>
	<section id="acc4">
		<h2><a href="#acc4">Title Four</a></h2>
		<p>This content appears on page 4.</p>
	<section id="acc5">
		<h2><a href="#acc5">Title Five</a></h2>
		<p>This content appears on page 5.</p>


As before, the clickable section heading is contained within each section as the initial h2 tag.


First, we’ll style the article container and section elements. Each section starts in its closed state with a height of 2em (note that overflow is set to hidden):

	display: block;
	width: 30em;
	padding: 0.5em 0.5em 1px 0.5em;
	margin: 0 auto;
	background-color: #666;
	border-radius: 5px;
	box-shadow: 0 3px 3px rgba(0,0,0,0.3);

article.accordion section
	display: block;
	width: 28em;
	height: 2em;
	padding: 0 1em;
	margin: 0 0 0.5em 0;
	color: #333;
	background-color: #333;
	overflow: hidden;
	border-radius: 3px;

The section title is now styled to use all the available room in the closed state:

article.accordion section h2
	font-size: 1em;
	font-weight: bold;
	width: 100%;
	line-height: 2em;
	padding: 0;
	margin: 0;
	color: #ddd;

article.accordion section h2 a
	display: block;
	width: 100%;
	line-height: 2em;
	text-decoration: none;
	color: inherit;
	outline: 0 none;

We can now ‘open’ the active section using the :target selector. We set a larger height and background color, then enlarge and re-color the title too:

article.accordion section:target
	height: 15em;
	background-color: #fff;

article.accordion section:target h2
	font-size: 1.6em;
	color: #333;

If necessary, you can set the section height to auto so it uses the minimum space it requires. However, that makes it impossible to add nice CSS3 transitions which smoothly resizes the element…

article.accordion section,
article.accordion section h2
	-webkit-transition: all 1s ease;
	-moz-transition: all 1s ease;
	-ms-transition: all 1s ease;
	-o-transition: all 1s ease;
	transition: all 1s ease;

View the demonstration page…

If anything, this CSS is simpler than the tab control and looks better. But vertical accordions are easy — horizontal ones are far cooler!…

  • As someone who HATES these types of effects on pages, I have to say this and the tabs one are cool because they address my biggest problems with these types of animations…

    Unlike scripted versions it doesn’t break forward/back navigation… and if you link directly to one of the subsections it will open it automatically. Personally, I’d axe the transition nonsense since when I click on things I’m much more impressed with it opening “NOW” instead of a few moments from now after some stupid animation, but that’s more of a personal preference than a criticism of some very impressive use of CSS3.

    NOT wild about it relying on fixed heights though… can’t you just height:auto on those instead of the 15em?

    Also, this should work just fine without that article/section HTML 5 nonsense, right? Avoid the whole idiotic bloat/redundant tags and loosening of structural rules to the point of validation being pointless?

    • If you don’t want animation, you can set height:auto and it’ll work fine.

      And yes, it would work perfectly well without HTML5 tags if you don’t want to use them.

      • Wouldn’t the animation still work with switching between the 2em and auto? I mean, to lose the animation you just yank the transitions…

        … or are you saying that transitions don’t work on auto values? I’ve not really played with transitions enough on that one.

      • Unfortunately not. You can’t animate between non-measurement values such as ‘auto’. Technically, there’s no reason why the browser couldn’t implement it so it may appear at some point.

    • Matthew P.

      Craig hasn’t inserted these tags needlessly, if article and section weren’t being used they’d just be replaced with divs or some other block level elements – might as well use a tag that provides some semantic information if they have to be there anyway. I’d hardly say it’s bloated, redundant or loosening any rules to do so, in fact it’s just the opposite when done properly.

      Also keep in mind that the correct semantic tags to use are determined by the content they will contain, the example is just an example, so choose tags case by case accordingly.

      Using an article divided into sections will tell screen readers and search engines that the content can be treated independently of, and makes sense out of context from the rest of the page, and that each section is a distinct but related part of this independent content. It makes no difference to how the page is rendered of course,but will make a difference in how automated systems may choose to order, weigh and present this content, and how users may be allowed to interact with it.

      • In other words, the job of the EXISTING semantic tags inside it like the H2’s to indicate the start of new subsections, making the use of “section” applying extra semantics for nothing — much less article? (if it’s all one article, it should probably have a h2 with all those being h3’s)

        Of course with the new structural rules for HTML 5, shouldn’t those all be H1’s? :D

    • “Unlike scripted versions it doesn’t break forward/back navigation…”

      True… or false? Only amateur scripted versions would suffer from this, right? If you really want, you can implement that behavior.

      One I don’t agree that is the right one, though. If I understand correctly, then you see as mandatory TOCs of fragments for each page. Where as now you rely on the occasional tabs or accordions for in-page forward/back navigation games.

  • mick

    Seems a little buggy. There is some odd movement on the below para’s and once you’ve hit a few tabs, the “Back Button Arrow” makes you go through the tabs again as if they were full pages.
    (or is that only for the demo)

    I do like it though, but to newb like me seems like the bugs woud be hard to iron out.

    “SitePoint is King”

    • Which browser have you noticed it on? In my testing, Firefox’s animation seemed best. Chrome/Safari can be a little quirky now and again, but it’s generally OK. Opera seems to queue transitions so the heading gets resized after the content box – but it still works fine. And IE9 won’t show any animation.

      Remember that transitions are beta technologies. They may change or never reach an agreed standard … although that seems unlikely.

  • Again… :)

    CSS3: “I can do it now!” OK, CSS3, we believe you, but, are you better at it, or are you just the new kid on the block?

    And I’m sure many-a-many other beautiful yet unusable and unreliable stuff can be made by CSS3. Yet the user (and the client) need not to hear or feel about you struggling, as a developer.

    One thing that caught my attention: sending messages like “tell them to upgrade” to your visitors often borderlines ridicule ;)

    How would you like if someone said: “I’m sorry, you need to upgrade your car to the newest spoilers to take that road” ?! How could vain stuff prevent my free traveling !? On the internet or otherwise ?!

    A solutions is not a solution if it relies on the users being understanding to the “needs” a web developer has. Right?

    So, once again, in the name of progressive enhancement done right, javascript is the tool for this. A few trendy unorthodox implementations in CSS3 will never be able to eliminate the need for a scripting language in web. So why bother? Trends like these will only be able to surface two headed monsters that can speak two ways but none is articulate enough to make sense completely.

    Everyone and their mother should avoid aggressive-in-a-bad-way UXs Playing around so called new technologies (immature implementations, by their real name) doesn’t excuse anyone from properly understanding the working standards in building web interfaces: basic to complex.

    “God help those that don’t have” doesn’t equal progressive enhancement nor graceful degradation the way CSS3 tries to interferes with programmatic behavior. It equals to: “I think I can give you only this now, I’m not sure. Now be on your way now and don’t bother me anymore!”.

    • As mentioned, the selectivizr shim IS JavaScript which allows this to work in IE6, 7 and 8. Besides, telling users to upgrade is no more ridiculous than telling them to enable JavaScript (admittedly, that affects fewer people, but some users can’t do it). And there’s nothing to stop you using this as a basis for further scripted enhancements so it works with and without scripting.

      But why do you consider (presentational) animation to be “programmatic behavior”? If that’s the case, shouldn’t link hover effects also be scripted? The only reason animation’s been scripted until now is because there was no other alternative. That’s no longer the case and newer effects such as CSS3 transformations couldn’t easily be achieved using JavaScript anyway.

      I can understand why you’re uncomfortable with it — I was too. But technologies and techniques change. There are situations when scripted animation will be required, e.g. canvas/SVG manipulation, intercepting incomplete animations, etc. But, for simple effects, CSS3 is far quicker to implement and will always run faster.

      • Except this is programatic behavior not (presentational) animation.

        This part of CSS, 3 or whatever, helps substite the lack of javascript skills for some web developers.

        Maybe you’re right, previously, the lack of serious CSS implementations lead to the use of javascript instead. However, now it’s not the time to turn tables and to abuse CSS the same way javascript was.

        Before CSS3 came and started to “help” designers to quickly solve (in a wrong way) different needs, there was a time when CSS was about finally getting out of the tables layout zone and tackle the biggest issues CSS had from the start.

        But now CSS solves programatic behaviour better than presentational issues and yet the basics are pretty much the same ancient solutions. And I mean layouts, box models etcetera.

      • Why is it programmatic behavior? We can obviously argue ad-infinitum about that, but I don’t see any major differences between this and link hover/active states. Only the styling is changed; it’s not possible to implement CSS3 programmatic actions in such as stopping the animation part way through or reacting to other user actions.

        Designers may abuse CSS3 but they’ll also abuse JavaScript (which is worse). There is no black and white distinction between content, presentation and behavior; the lines have always been blurred and developers won’t necessarily adopt the best choice.

        You’re concerned novice developers can now implement effects which previously required good JavaScript coding skills. That’s always been the situation as IT and the web evolve. I used Java applets to implement rollover effects in the mid-90s — it was horrible, but I could have argued the same point you’re making today. I’m afraid Pandora’s box is already open; you may not consider it progress, but few people will continue to code JavaScript animations when better effects can be achieved with a line or two of CSS.

      • Well, when you put it that way, sure, anything goes.

        My point is that there are many ways to do it, but just a few are the proper ones.

        The difference I see here is the difference between how a link looks like and how a link acts like.

        It’s not the animation I’m questioning here, it’s the fact that stuff is being manipulated, hidden, revealed by CSS.

        When you make a click, and then actions such as hidden or reveal happen, that’s not presentation, that’s programatic behaviour to me.

        Finally, I have nothing against making the web accessible to those that want to be part of it. But loose views on the way things are done are the ones that kept table layouts in play so many many years.

      • Even basic HTML without CSS or JavaScript can effectively hide or show content simply by scrolling the page to the correct place. Admittedly, it’s not quite the same but there are other HTML features that could be considered programmatic, e.g. form reset buttons, file select dialogs, and many of the HTML5 form fields.

        As the web evolves, we’re certain to have less reliance on scripting because regularly-required features will be implemented directly into HTML or CSS. Perhaps that’s not always progress, but I prefer that to the stagnation we experienced in the first half of the last decade.

      • … or maybe something like jQuery will become accessible enough so that scripting will be guiding proud and effortlessly every novice’s page, letting CSS be what it supposed to be :)

        The way I see it, smarter scripting, not wrong and dizzy CSS, is what web needs. Web technologies aren’t mature yet exactly because javascript is used for CSS and CSS tries to do scripted jobs.

        Every web technology involved, be it HTML, CSS or JavaScript, needs to recognize its proper place and do *that* job, better and better. If an operating system were to evolve like web does, we would be using PowerPoint for spreadsheet calculations, since it can be more easily manipulated into presentation.

      • While I generally agree with you, the distinction between content, presentation and behavior isn’t always clear-cut and developers will choose whichever decision benefits them.

        MS Office is a great analogy. Users often add complex tables to Word documents which should have been created in Excel. Similarly, people will use Excel for some simple documents. While it may not be particular efficient or effective, it got the job done.

Get the latest in Front-end, once a week, for free.