From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
Today we’ll experiment some more with the adjacent and general sibling combinator and the :checked pseudo-class. Using hidden inputs and labels, we will create an accordion that will animate the content areas on opening and closing.
There are many variations of CSS-only accordions around, most of which are implemented using the :target pseudo-class. The problem with using :target is that we can’t really close the content areas again or have multiple sections open at the same time. By using hidden checkboxes, we can control the opening and closing. Alternatively, we can also use radio buttons if only one section should be open at a time.
So, let start!
Please note: the result of this tutorial will only work as intended in browsers that support the CSS3 properties in use.
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
The Markup
We will be going through an example that uses checkboxes where one content section is open by default (the input needs to be ‘checked’). Everything will be wrapped in a container with the class ac-container. For each item, we will have a checkbox, a label and an article which is the content section of that item:
<section class="ac-container"> <div> <input id="ac-1" name="accordion-1" type="checkbox" /> <label for="ac-1">About us</label> <article class="ac-small"> <p>Some content... </p> </article> </div> <div> <input id="ac-2" name="accordion-1" type="checkbox" checked /> <label for="ac-2">How we work</label> <article class="ac-medium"> <p>Some content... </p> </article> </div> <div><!--...--></div> </section>
Note that we need to give each input an ID which we will then use in the for attribute of the label. We need this in order to check the checkbox when clicking on the label.
Each article will have a class that will help us determine to which height we it to expand to. (Optimally, we could use ‘auto’ as the expanded height value, but unfortunately it will not animate like that.)
Let’s have a look at the style.
The CSS
I will omit all the vendor prefixes, but you will, of course, find them in the files.
Let’s define a width for the accordion and center it:
.ac-container{ width: 400px; margin: 10px auto 30px auto; }
Next, we’ll make the labels appear as clickable buttons by giving them some slick background gradient. With multiple box shadows, we’ll create a subtle border and an inset effect. We’ll also set the z-index to 20, to make sure it will be on top of the content section:
.ac-container label{ font-family: 'BebasNeueRegular', 'Arial Narrow', Arial, sans-serif; padding: 5px 20px; position: relative; z-index: 20; display: block; height: 30px; cursor: pointer; color: #777; text-shadow: 1px 1px 1px rgba(255,255,255,0.8); line-height: 33px; font-size: 19px; background: linear-gradient(top, #ffffff 1%,#eaeaea 100%); box-shadow: 0px 0px 0px 1px rgba(155,155,155,0.3), 1px 0px 0px 0px rgba(255,255,255,0.9) inset, 0px 2px 2px rgba(0,0,0,0.1); }
On hover, we’ll make the label white:
.ac-container label:hover{ background: #fff; }
When we click on a label, the checkbox get’s checked and when that happens we want the respective label to have the following “selected” style:
.ac-container input:checked + label, .ac-container input:checked + label:hover{ background: #c6e1ec; color: #3d7489; text-shadow: 0px 1px 1px rgba(255,255,255, 0.6); box-shadow: 0px 0px 0px 1px rgba(155,155,155,0.3), 0px 2px 2px rgba(0,0,0,0.1); }
As you can see, we are using the adjacent sibling combinator to select the label since it is directly preceded by the checkbox input.
Let’s add a little arrow icon on hover. For that we’ll simply use the pseudo-class “after” so that we don’t add unecessary markup:
.ac-container label:hover:after, .ac-container input:checked + label:hover:after{ content: ''; position: absolute; width: 24px; height: 24px; right: 13px; top: 7px; background: transparent url(../images/arrow_down.png) no-repeat center center; }
For the “selected” item, we want to show the up-pointing arrow:
.ac-container input:checked + label:hover:after{ background-image: url(../images/arrow_up.png); }
And since we don’t want the inputs to show, we’ll hide them:
.ac-container input{ display: none; }
The content area will have an initial height of 0px and any overflow will be hidden. We’ll add a transition for the height and for the box shadow. The transition that we are adding here will act upon “closing” the item. We define another transition for the selected item. So, we can basically control the two behaviors by doing this. As you can see, we will make the closing a bit faster than the opening.
.ac-container article{ background: rgba(255, 255, 255, 0.5); margin-top: -1px; overflow: hidden; height: 0px; position: relative; z-index: 10; transition: height 0.3s ease-in-out, box-shadow 0.6s linear; } .ac-container input:checked ~ article{ transition: height 0.5s ease-in-out, box-shadow 0.1s linear; box-shadow: 0px 0px 0px 1px rgba(155,155,155,0.3); }
Let’s style the content a bit:
.ac-container article p{ font-style: italic; color: #777; line-height: 23px; font-size: 14px; padding: 20px; text-shadow: 1px 1px 1px rgba(255,255,255,0.8); }
Now we define the three classes for the different heights. These are the heights that an item’s content will animate to:
.ac-container input:checked ~ article.ac-small{ height: 140px; } .ac-container input:checked ~ article.ac-medium{ height: 180px; } .ac-container input:checked ~ article.ac-large{ height: 230px; }
As already mentioned, “auto” height would of course be the best option here, but since we can’t animate to that, we need to set some heights for the transition.
Please note that in some mobile browsers, clicking on a label might not trigger the checking or focusing of the associated input.
Demos
And that’s it! I hope you enjoyed this tutorial and find it useful!
nice
Does not work on ipad.
Nice work… simple but stunning.
This is nice with CSS3 but it looks ugly in IE 7, you need to do a fix that will atleast show the accordions. Rest of looks great in other browsers.
Does it work on the iPad?
I really enjoy CSS3, and I never thought that it can get powerful enough to be used for something like “accordian” at all.
Great code, thanks.
AWESOME! Great.. you’r the best as always 😉
Here’s something similar, but with hover effect: slide menu
Again a very useful tool, I used it for FAQ for my website. Thanks !
The Demo is not working on my iPad.
WOW HTML attribute there…xixixii
ty ty for coding \m/
HTML5 i mind 😀
Nice Trick.. 😉 Awesome
Fantastic tut! I can’t wait to use this.
couldn’t you just get the .height(); of the content and then add it to the padding that way you don’t have to set heights and your accordion will be scalable to whatever content exists and have the same padding?
Demo not working at all
in Firefox 3.6.27,
under XP-SP3.
LOL
this is awesome…nice tutorial, thanks for sharing!
Thank you, Mary, for the wonderful idea!
I am amazed at how quickly gaining momentum pseudo-classes …
The main thing that I liked your idea – is that the accordion is equally good for both PC and mobile, to which we are now doing the basic rate.
Regarding comments that the accordion looks ugly in IE7: what looks good in all browsers, IE?! If the user wants to get a beauty, let set a really good browser – it’s not a problem, is not it?
thanks a lot, Marylou. You’re still the best.
nothing special…
Clean, beautifull …
Tnkxs for sharing 😉
Dn.
Because the height limit was set! It is better to add a variable overflow too 😉
how do you guys get this ideas, this thoughts that shows you what to do ?
i want to be so creative but i have no idea how….
Built something similar, but with simpler markup and effects — http://alexindigo.github.com/accordion/
And css-only lightbox: http://alexindigo.github.com/lightbox/
Enjoy 🙂
Looks insane thank you!
Guys, which one is better.. This one or THIS ONE
Guys, which one is better.. This one or THIS ONE
Very nice. I used a similar technique with the general sibling combinator to “filter” elements based on the data attribute. http://jsfiddle.net/joshvogt/NdP3L/
I’ve never been more impressed with a CSS blog. It seems you have fresh content almost daily and will almost single-handedly usher in the CSS functionality age.
Great article, simply great.
If you add the css property of: translate3d(0,0,0) then it will force the animation to trigger hardware acceleration in Safari for more optimized animations.
“In essence, any transform that has a 3D operation as one of its functions will trigger hardware compositing, even when the actual transform is 2D, or not doing anything at all (such as translate3d(0,0,0)). Note this is just current behaviour, and could change in the future (which is why we don’t document or encourage it). But it is very helpful in some situations and can significantly improve redraw performance.”
http://24ways.org/2010/intro-to-css-3d-transforms
You should also think about using CSS keyframes and the code used on this site to improve your CSS transitions.
http://daneden.me/animate/
With this solution, would it be possible to create a “close all” and “open all” button? If you add that, then this would be PERFECT!
So far, it’s one of the best I have seen on the web. I just want to help make it perfect 😉
If you wrapped the accordion in a form-element, you could use a input with type=”reset” as the “close all” button. A “open all” button would be hard without using JS to check the boxes though.
Very nice and clean work here. The menu looks great and works really well.
I did something very similar a few months ago, but I also did an example for a horizontal accordion: http://www.mraffaele.com/blog/2011/10/25/css-accordion-no-javascript/
I’m trying to do an accordion effect that works on iphone, ipod touch and android, this doesn’t work on those, I need it for a school proyect, i’m learning how to make html5 web mobile apps, if I try to click the checkbox it doesn’t let me see whats inside, does anybody knows why? or a tutorial on how to make an accordion menu for the ipod touch/iphone using html 5.
Excellent……
As always, very nice tutorial. So much things can be done using jQuery. thank you!
You mentioned that you can’t transition to height:auto. To overcome that you could transition on max-height instead. You set it to 0 for the closed state and then to a value larger than the largest content height you expect on open. You can learn more about this technique in this article on theNerdary.
Hi there!
Nice tutorial.
I´m having a problem, i want to remove the border or change the color but i´m not beeing able to do this.
What´s the class for this? Can you help give a hint on this?
Regards
Hi Mary Lou
Recently I’ve spent a lot of time searching for a vertical accordion menu to use on a e-commerce project I am currently developing. My problem is with most tutorials the jquery involved conflicts with code I am already using in my slideshow. A full css version like the one you have demonstrated here would be the perfect solution! It is a shame however that the menu is not supported in older versions of internet explorer.
thx
Look like pretty good…!
Great tutorial. It really is amazing what is possible with CSS3. Web design has changed forever for the better! I will definitely be using this in a future website.
hi mary (Manoela)
your work is amyzing, thanks for sharing.
Using your checkbox logic I made a notification bar just like stackexchange and a simple news ticker. Here is the link of it
http://webstutorial.com/css3-news-ticker-css3-notification-bar-stackexchange/css3
Thanks for explaining the checkbox logic.
Hello, I am having an issue with this. I did the accordion but there is SOMETHIGN I erased or added that is adding the checkboxes to the form. What could this be? You can check it out at www.http://cruzbarcelona.com/chupiman/home.html
Can anyone help me?
Great demo, but unfortunately not working on iOS. : /
Also on Android is not working…
It must be something related to mobile browsers and CSS3 🙁
It´s a pity – really great tutorial, BUT… Has anyone an idea to fix the “mobile problem” (iOS + Android)?
I thought the new mobile browsers are fine with HTML5 + CSS3…
I’m having problems nesting tags within the accordion. input works but not when i try to add any ideas why this wouldn’t be working ?
I’m having problems nesting “input” tags within the accordion. “select” input works but not when i try to add input type=”text” any ideas why this wouldn’t be working ?
This is beautiful, but fails to work on the Android. All panels open initially and the “accordion” fails to work. Have you a tweak? This by itself would make a great mobile website!
Is it possible to make this sliding in the horizontal?
Thanks