Dynamic CSS3 Animated Accordian Menu
So I’ve been doing some more CSS3 experiments and I think I’ve cracked the Accordian thing. I actually tried this out ages ago 2008 Demo and ran into the same problems other people had later on, namely animating the height of an enclosing element couldn’t be dynamic it had to be fixed.
What do I mean? If your using CSS3 Transitions you have to have a start and end value, say.
div {
-webkit-transition: all .5s ease-in-out;
height: 0px
}
div:hover {
height: 100px;
}
The issue was how do you know how high each of the accordian panels are that your animating? Each one might have a different number of elements. Now CSS doesn’t allow any sort of loops or math like Javascript so you can’t find out the height based on the number of elements.
Then it hit me! Why bother with the container height and instead focus on the elements inside it! All the things you’d put inside a div are going to have static values right, like say an ‘a’ tags height. Why not animate that instead thus causing the container to collapse.
Let’s start with an Accordian menu. Here’s the basic markup, a simple ul with li’s.
<ul class="menu">
<li class="title"><a id="1" href="#1"><span>Stuff</span></a>
<ul>
<li><a href="#">list</a></li>
<li><a href="#">list</a></li>
<li><a href="#">list</a></li>
<li><a href="#">list</a></li>
<li><a href="#">list</a></li>
<li><a href="#">list</a></li>
<li><a href="#">list</a></li>
<li><a href="#">list</a></li>
</ul>
</li>
<li class="title"><a id="2" href="#2"><span>Stuff</span></a>
<ul>
<li><a href="#">list</a></li>
<li><a href="#">list</a></li>
<li><a href="#">list</a></li>
</ul>
</li>
</ul>
You’ll notice that the ‘a’ has an ‘id’ and the ‘href’ is targeting that id. This allows us to use the CSS3 :target selector for our animation, you’ll notice it’s actually targeting itself! I’ve done this for a reason.
.title ul li a {
-webkit-transition: all .5s ease-in-out;
height: 0px;
display: block;
}
:target + ul li a {
height: 30px;
}
In the above CSS you’ll see I’ve used the ‘+’ adjacent sibling selector when using :target. This says effect the next ul’s list items ‘a’ tags. When they shrink the enclosing ‘ul’ is then effectively invisible as there is no ‘height’ inside it.
Funnily enough it’s been two years since I tried the original CSS3 accordion with the height issues and this will still only render in Webkit browsers so you’ll need Safari or Chrome to view it properly, it will come up in Firefox but without all the CSS3 fluff! This is an example of a menu full of links.
The next example is a text box accordian. This time instead of worrying about the container height I’ve targeted the paragraph tag. I’ve now put the ‘id’ in the list item and used the decendant selector ‘>’ to target all ‘p’ tags inside that list item.
<ul class="menu">
<li class="title" id="1"><a href="#1"><span>Stuff</span></a>
<p>Lorem ipsum dolor sit amet........</p>
</li>
<li class="title" id="2" ><a href="#2"><span>More Stuff</span></a>
<p>Lorem ipsum dolor sit amet.........</p>
<p>Lorem ipsum dolor sit amet..........</p>
</li>
</ul>
Here’s the CSS. The target parameters are padding, line-height and margin-bottom. The line-height and margin-bottom are doing all the work and the ‘p’ tag is given overflow:hidden; to make it disappear.
.title p {
-webkit-transition: all .5s ease-in-out;
background: #fff;
padding: 0em 20px 0em 20px;
line-height: 0em;
margin-bottom: -1.9em;
overflow: hidden;
color: #fff;
}
:target > p {
padding: .5em 20px 1em 20px;
line-height: 1.2em;
margin-bottom: 0em;
color: #070707;
}
Here’s the demo. Even works with an image. Check the scource! This is totally fucked in Firefox as yet so don’t bother.
Sorry for the scrappy code but this was only an experiment (proof of concept) which works for now only in Webkit, as yet to my knowledge this is the only accordian that can generate dynamic heights for panels. And yes, it looks shit in IE8!!
Any thoughts or improvements welcome!
Posted on Sunday, April 25th, 2010 at 2:34 pm.
Filed under CSS, Web Design.






Nice work Toby! One thing I find particularly interesting is how it has back button support automatically. If this was JavaScript, and that was the desired effect, that would have to be specially written in, which is no small chore. But that brings up the other question… do we even want back button support on accordions? And is it possible to kill it?
Ha! I never even noticed that! It was late though!
[...] This post was mentioned on Twitter by tobypitman. tobypitman said: CSS3 accordian with dynamic height. Just an experiment! http://bit.ly/9peLob [...]
[...] Код для примера и ссылка на демо на этой странице. [...]
[...] 11. Dynamic CSS3 Animated Accordian Menu [...]
Wow, it doesn’t work in FF 4.0…. ahm) Great tut!
It’d be nice if the transition effect could go from a height of 0px to a height of auto. However, this doesn’t seem to work, at least not in Firefox
Hi, I really love the way this works, it’s the best implementation I’ve found on the web. I’m still quite new to all this so I have a few questions:
Is it possible to make it work on hover and then stay open whilst hovering over the sub menu?
Is it possible to make it so that when clicked it will go to another page? (as at the moment the a href is targeting itself to make the accordion work)
When on a page where the link is in the sub menu is it possible to to kep the accordion open?
This might make more sense if you go to where I’m testing this out http://sbx.me/sadwrn
Any help would be appreciated.
Thanks
Hi, not sure if it will be successful with :hover. I did try that but ran into the same issue your test site is having where it keeps closing.
Same with the linking.
This was, ‘and still is’ a bit experimental and i’d probably urge you to go with a more traditional javascript approach in production, CSS3 transitions will cause more grief than necessary when it come to wide scale browser compatibility. On something as important as navigation I’d err on the side of caution.
If your looking for a way to keep the panels open when using jQuery you might want to have a look at this.
http://www.tobypitman.com/multiple-collapsable-panels-with-cookies/
Sorry I can’t be more help!