Skip to content

Accordion using only CSS

An accor­dion effect can be achieved using CSS3’s :target pseudo-class, with­out requir­ing JavaScript. Using the pro­pri­etary -webkit-transition prop­erty this accor­dion can also be ani­mated.

Result

CSS3 Accor­dion
Works in browsers that sup­port the :target pseudo-class, see the Quirks Mode com­pat­i­bil­ity tables. Ani­ma­tion works in recent WebKit based browsers.

How To

Each part of the accor­dion has an ID, head­ing and con­tent region. The header includes a link that matches the section’s ID, whilst the con­tent is wrapped in a con­tainer which will con­trol its display.

<div class="accordion">
	<h2>Accordion Demo</h2>
	<div id="one" class="section">
		<h3>
			<a href="#one">Heading 1</a>
		</h3>
		<div>
			<p>Content</p>
		</div>
	</div>
	<div id="two" class="section">
		<h3>
			<a href="#two">Heading 2</a>
		</h3>
		<div>
			<p>Content</p>
		</div>
	</div>
</div>

The CSS then relies on the :target pseudo-class to apply dif­fer­ent styles to the cho­sen sec­tion — increas­ing the height and, in large con­tent cases, alter­ing the over­flow behav­iour to allow scrolling. To ani­mate the open­ing and clos­ing of sec­tions the -webkit-transition prop­erty is needed (doc­u­men­ta­tion), in this case act­ing on the height attribute for a dura­tion of 0.3 sec­onds using the ease-in tim­ing function.

Strip­ping out the styling, the CSS boils down to:

.accordion h3 + div {
	height: 0;
	overflow: hidden;
	-webkit-transition: height 0.3s ease-in;
}

.accordion :target h3 + div {
	height: 100px;
}

.accordion .section.large:target h3 + div {
	overflow: auto;
}

Cri­tique

Obvi­ously this approach has its lim­i­ta­tions. Mul­ti­ple open accor­dions on one page wouldn’t be pos­si­ble — restricted by a URI’s one frag­ment iden­ti­fier limit; as one accor­dion opens the other would lose the tar­get and auto­mat­i­cally close. Sim­i­larly, pages that use a frag­ment iden­ti­fier for every­day use will notice odd­i­ties — take for instance when using top links to return to the top of the page, any accor­dion would, in this case, reset. Other uses include acces­si­bil­ity links and sim­u­lated page his­to­ries when using Ajax.

Paul Hayes Paul Hayes is a developer at Last.fm. You should follow him on Twitter, where he talks about UX, HTML, CSS and JavaScript, amongst other cool stuff.

17 Comments

  1. Alejandro

    Check http://​aranedaale​jan​dro​.word​press​.com for another CSS only accor­dion menu (last ver­sion with slid­ding effect with SMIL for IE and CSS3 tran­si­tions for the rest)

  2. Juegos

    Love it, thank you for this trick. Your effort is appreciated.

  3. Greg Babula

    this is great, thanks!

  4. Deepak Kaletha

    Great Arti­cle … thnks

  5. Zack

    I have been try­ing to inte­grate this accor­dian effect into a mobile web­site for a client with­out much avail. But your solu­tion works per­fectly in both iOS and android devices. Thank you!

  6. morpheus7

    Hi,

    I have tried using it on my site and it does work great, but I would like to switch the Head­ing 1 text with an image. As image is inserted into the place of text trough tags, the area remains click­able, but doesn’t expand any longer. I tried play­ing around with it, but I sadly can’t come up with any kind of solution.

    Could you please offer me your insight on the mat­ter how to make it work.

    Thank you and thanks again for posting!

  7. Andy
  8. bastek

    Really cool! but sadly it doesn’t work in IE
    :(
    I per­son­ally use Opera, but site must work in all browsers…

  9. Perry

    @bastek: it works in IE9. As the author said, “Works in browsers that sup­port the :tar­get pseudo-class”. IE before IE9 does not sup­port it.

  10. Brent

    Excel­lent, I was look­ing for this, thank you.

    IE<9 needs con­di­tional stylesheet.

    Inte­grate also :hover and :focus?

    B
    http://​www​.kcl​.ac​.uk/​i​p​/​b​r​e​n​t​c​u​n​n​i​ngham

  11. Michaele

    Paul, Thanks for post­ing this — nice solu­tion for mobile web!

  12. Noah

    Maybe I’m a goof but when I try to have the height of each “fold” just be deter­mined by the inte­rior con­tent by using auto or remov­ing height the ani­ma­tion doesn’t work any­more. I’m sorry if this is a strange ques­tion, I’m so used to using js for some of these things.

  13. jean

    In my opin­ion the biggest down­side is the fact that the nav­i­ga­tion is made through links and this makes the page to scroll in order to put the referred link on top of the page. I dont think there is an easy way to solve this prob­lem unfortunately.

  14. TheBoy

    Está genial, me encanta!
    It’s great, I love it!

  15. Nicholas Credli

    Cool!

    Ani­ma­tion would work on IE, Fire­fox, and Opera if you add the fol­low­ing lines under –webkit-transition attrib.:

    –o-transition: height 0.3s ease-in;
    –moz-transition: height 0.3s ease-in;
    –ms-transition: height 0.3s ease-in;

    Nick

  16. Kunha

    Great css script :)

    i did a change to avoid scroll bars

    .accor­dion h3 + div {
    height: 0;
    over­flow: hid­den;
    –webkit-transition: height 0.3s ease-in;
    }

    .accor­dion .section:target div {
    height: 100%;
    posi­tion: rel­a­tive;
    float: left;
    width: 100%;
    padding-bottom: 10px;
    }

  17. WesTurner

    @Al:

    It does work in IE9+ and FF8+ but this demo is miss­ing the –moz, –o, and –ms fla­vors for the tran­si­tion css3 attribute.

    It would be nice if Paul updated his CSS across the site to include the browser-specific imple­men­ta­tions of these CSS3 attrib­utes. Bet­ter yet, the browser mak­ers should stop using these exten­sions and just use the actual attribute, TRANSITION.