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 [...]