Pure CSS(3) accordion

I tend to do a lot of tinkering with code, and came up with something that’s not so new, but still, in my opinion, pretty cool. An accordion using nothing but semantic HTML, CSS and some nice progressive CSS3. There are also two versions, a horizontal one and a vertical one.

Demo

This article has been ported from the now-defunct Venturelab Devblog, where I had originally authored it.

Horizontal accordion

Let’s start with the markup for the horizontal accordion, it’s really nothing special, just some good ol’ semantic HTML:

<ul class="accordion">

  <li class="slide-01">

    <div>

      <h2>Slide one</h2>

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse id lobortis massa. Nunc viverra velit leo, sit amet elementum mi. Fusce posuere nunc a mi tempus malesuada. Curabitur facilisis rhoncus eros eget placerat. Aliquam semper mauris sit amet justo tempor nec lacinia magna molestie. Etiam placerat congue dolor vitae adipiscing. Aliquam ac erat lorem, ut iaculis justo. Etiam mattis dignissim gravida. Aliquam nec justo ante, non semper mi. Nulla consectetur interdum massa, vel porta enim vulputate sed. Maecenas elit quam, egestas eget placerat non, fringilla vel eros. Nam vehicula elementum nulla sed consequat. Phasellus eu erat enim. Praesent at magna non massa dapibus scelerisque in eu lorem.</p>

    </div>

  </li>

  <li class="slide-02">

    <div>

      <h2>Slide two</h2>

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse id lobortis massa. Nunc viverra velit leo, sit amet elementum mi. Fusce posuere nunc a mi tempus malesuada. Curabitur facilisis rhoncus eros eget placerat. Aliquam semper mauris sit amet justo tempor nec lacinia magna molestie. Etiam placerat congue dolor vitae adipiscing. Aliquam ac erat lorem, ut iaculis justo. Etiam mattis dignissim gravida. Aliquam nec justo ante, non semper mi. Nulla consectetur interdum massa, vel porta enim vulputate sed. Maecenas elit quam, egestas eget placerat non, fringilla vel eros. Nam vehicula elementum nulla sed consequat. Phasellus eu erat enim. Praesent at magna non massa dapibus scelerisque in eu lorem.</p>

    </div>

  </li>

  <li class="slide-03">

    <div>

      <h2>Slide three</h2>

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse id lobortis massa. Nunc viverra velit leo, sit amet elementum mi. Fusce posuere nunc a mi tempus malesuada. Curabitur facilisis rhoncus eros eget placerat. Aliquam semper mauris sit amet justo tempor nec lacinia magna molestie. Etiam placerat congue dolor vitae adipiscing. Aliquam ac erat lorem, ut iaculis justo. Etiam mattis dignissim gravida. Aliquam nec justo ante, non semper mi. Nulla consectetur interdum massa, vel porta enim vulputate sed. Maecenas elit quam, egestas eget placerat non, fringilla vel eros. Nam vehicula elementum nulla sed consequat. Phasellus eu erat enim. Praesent at magna non massa dapibus scelerisque in eu lorem.</p>

    </div>

  </li>

  <li class="slide-04">

    <div>

      <h2>Slide four</h2>

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse id lobortis massa. Nunc viverra velit leo, sit amet elementum mi. Fusce posuere nunc a mi tempus malesuada. Curabitur facilisis rhoncus eros eget placerat. Aliquam semper mauris sit amet justo tempor nec lacinia magna molestie. Etiam placerat congue dolor vitae adipiscing. Aliquam ac erat lorem, ut iaculis justo. Etiam mattis dignissim gravida. Aliquam nec justo ante, non semper mi. Nulla consectetur interdum massa, vel porta enim vulputate sed. Maecenas elit quam, egestas eget placerat non, fringilla vel eros. Nam vehicula elementum nulla sed consequat. Phasellus eu erat enim. Praesent at magna non massa dapibus scelerisque in eu lorem.</p>

    </div>

  </li>

  <li class="slide-05">

    <div>

      <h2>Slide five</h2>

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse id lobortis massa. Nunc viverra velit leo, sit amet elementum mi. Fusce posuere nunc a mi tempus malesuada. Curabitur facilisis rhoncus eros eget placerat. Aliquam semper mauris sit amet justo tempor nec lacinia magna molestie. Etiam placerat congue dolor vitae adipiscing. Aliquam ac erat lorem, ut iaculis justo. Etiam mattis dignissim gravida. Aliquam nec justo ante, non semper mi. Nulla consectetur interdum massa, vel porta enim vulputate sed. Maecenas elit quam, egestas eget placerat non, fringilla vel eros. Nam vehicula elementum nulla sed consequat. Phasellus eu erat enim. Praesent at magna non massa dapibus scelerisque in eu lorem.</p>

    </div>

  </li>

</ul>

Here we have a simple unordered list containing a series of class-named list items and some content. Simple. The CSS is where it gets nifty:

/*------------------------------------*\
  ACCORDION
\*------------------------------------*/
.accordion{
  width:940px;
  overflow:hidden;
  list-style:none;
  margin-bottom:10px;
  text-shadow:1px 1px 1px rgba(0,0,0,0.25);
  background:blue;

  -moz-border-radius:10px;
  -webkit-border-radius:10px;
  -o-border-radius:10px;
  border-radius:10px;
}
.accordion li{
  float:left;
  width:20%;
  overflow:hidden;
  height:250px;
  -moz-transition:width 0.2s ease-out;
  -webkit-transition:width 0.2s ease-out;
  -o-transition:width 0.2s ease-out;
  transition:width 0.2s ease-out;
  -moz-transition-delay:0.15s;
  -webkit-transition-delay:0.15s;
  -o-transition-delay:0.15s;
  transition-delay:0.15s;
}
.accordion li:first-of-type{
  -moz-border-radius:10px 0 0 10px;
  -webkit-border-radius:10px 0 0 10px;
  -o-border-radius:10px 0 0 10px;
  border-radius:10px 0 0 10px;
}
.accordion li:last-of-type{
  -moz-border-radius:0 10px 10px 0;
  -webkit-border-radius:0 10px 10px 0;
  -o-border-radius:0 10px 10px 0;
  border-radius:0 10px 10px 0;
}
.accordion div{
  padding:10px;
}
.accordion:hover li{
  width:10%;
}
.accordion li:hover{
  width:60%;
}
.slide-01  { background:red; color:white; }
.slide-02  { background:orange; color:white; }
.slide-03  { background:yellow; color:#333; text-shadow:none; }
.slide-04  { background:green; color:white; }
.slide-05  { background:blue; color:white; }

It’s all fairly self-explanatory; first we have the .accordion class for the <ul> where we define a width and overflow hidden (to clear floats) and some other bits and pieces.

Next we float the list items left so they all stack up, give them a width of 20% (100% ÷ 5 = 20%) and give them overflow:hidden; so that no content breaks out of them. We also apply a fixed height that will nicely house all the content once the list items expand.

Now here’s a progressive bit, we tell the list items to transition their widths over a period of 0.2 seconds, easing out the animation.

Then after this we use the very handy :first- and :last-of-type selectors to round the top- and bottom-left and top- and bottom-right corners of the first and last list items respectively.

After this, we have a <div> to which we apply 10px padding. You could argue that this <div> is extraneous and that we can simply add the padding to the <li>s, and you’d be right, however this would make the percentage numbers for the width less nice to work with if you have to factor in paddings on the list items too.

Now we reach the bit that makes the accordion functional:

.accordion:hover li{
  width:10%;
}

What we do here is say as soon as I hover the <ul> make all the <li>s 10% in width.

This gives us 5 × 10% = 50%. 5 lots of 10% width list items in the list. We have a spare 50% of extra space in the list that we’d like to fill with whatever list item we are currently hovering.

10% list item + 50% dead space to fill = 60%

So what we do now is say make the list item that I am actually hovering 60% width.

.accordion li:hover{
  width:60%;
}

The whole functionality says when I hover the list make every list item 10% the width of the <ul> but make the one <li> that my cursor is over 60% of the width.

10% + 10% + 10% + 10% + 60% = 100%

The final block simply gives the list items some colour (colours of the rainbow, did you notice?).

When it’s all tied together you get a series of list items that alter their widths when hovered (but always totalling 100%). Then we use some CSS3 to round the corners in supportive browsers, and some transitions for the even more supportive browsers. This leaves us with an sliding accordion of rich HTML content that uses no JS and works even in IE7.

Vertical accordion

Just for an optional extra I decided to make the accordion work in a vertical orientation. We use exactly the same markup save for adding an ID to the <ul>, thus:

<ul class="accordion" id="vertical">

Now we stack the list items on top of one another by giving them a 100% width and this time applying the same 10% / 60% logic to the heights instead. The following code is all very self-explanatory so I’ll just leave you with it:

/*------------------------------------*\
  VERTICAL
\*------------------------------------*/
#vertical{
  height:300px;
}
#vertical li{
  float:none;
  height:20%;
  width:100%;
  -moz-transition:height 0.2s ease-out;
  -webkit-transition:height 0.2s ease-out;
  -o-transition:height 0.2s ease-out;
  transition:height 0.2s ease-out;
}
#vertical li:first-of-type{
  -moz-border-radius:10px 10px 0 0;
  -webkit-border-radius:10px 10px 0 0;
  -o-border-radius:10px 10px 0 0;
  border-radius:10px 10px 0 0;
}
#vertical li:last-of-type{
  -moz-border-radius:0 0 10px 10px;
  -webkit-border-radius:0 0 10px 10px;
  -o-border-radius:0 0 10px 10px;
  border-radius:0 0 10px 10px;
}
#vertical:hover li{
  height:10%;
  width:100%;
}
#vertical li:hover{
  height:60%;
  width:100%;
}

As we are inheriting the code from the horizontal version we do have to override the :hover state’s widths by explicitly setting them to 100%, but aside from that pretty much all we’ve done is applied the above theory to heights as opposed to widths. Magic!

By Harry Roberts on Thursday, February 17th, 2011 in Web Development. Tags: , , | 11 Comments »

+

11 Responses to ‘Pure CSS(3) accordion’


  1. Gabor said on 17 February, 2011 at 1:44 pm

    Okay, this is pretty cool! Thanks for sharing this! :-)


  2. Chris said on 18 February, 2011 at 4:12 pm

    Doesn’t work as expected on Firefox, but I’m sure you’ve noticed that!

    The vertical accordian looks great – could do with a bit of JS to give the transition some elasticity, but works well as pure CSS.

    The horizontal accordian – would probably look better with the text in a fixed width div, hidden by overflow. But again, I’m just splitting hairs – for a pure CSS solution, it’s ace.

    Good work. :)


  3. Steven said on 15 March, 2011 at 7:52 pm

    Would it be possible to change it so that instead of hover the accordion expands on click?


  4. Steven said on 17 March, 2011 at 5:30 pm

    Also wondering if there’s a way to include an arrow next to the ’s that would rotate upon hovering over the ’s.

    Great script btw!


  5. nate said on 9 June, 2011 at 3:59 pm

    How would you do this with FOUR list items?

    I have made a 4-item UL and tried to adjust the CSS accordingly, but there is always an additional space of rollover at the far right, even though there is actually nothing there.


  6. Harry Roberts said on 9 June, 2011 at 5:24 pm

    Give the list items a width of 25% instead of 20% and change the 60% to 70%.


  7. nate said on 9 June, 2011 at 7:15 pm

    You probably think I’m retarded, but for some reason when I touch the bottom of it, all the divs slide to the left and there is a huge blank space on the right.

    That was my problem trying to figure it out.

    But, it happens when I copy the whole thing exactly here though (with 5 columns), so I guess the problem is with some other style in my template.

    Thank you for helping me out. I thought I was missing something!


  8. Tina said on 8 November, 2011 at 9:21 pm

    how do i get the text not to wrap in the vertical version? I just want it to get cut off and then when you hover over you can see the whole text!


  9. habibi said on 4 December, 2011 at 10:16 pm

    i had to add
    padding:0px
    to the accordion class, then it worked


  10. Sam said on 16 January, 2012 at 3:50 am

    Great tut!

    Any way to completely hide a bit of content until the column is expanded?

    Say – when collapsed you see a number – each column has a number – when you hover it reveals more text and a picture.

    How could I accomplish this?

    Thanks for a great bit of code!


  11. Prodyot said on 29 January, 2012 at 9:10 am

    Very cool accordions in pure css.
    Great bud.
    I am definitely going to use it in my site :)
    I tested it in FIREFOX and it works in mine.
    It worked in Opera and Chrome too.
    I just hope my users have learnt to leave IE behind :)
    Thanks for sharing, bud.
    Best wishes.


Leave a Reply

Respond to Pure CSS(3) accordion

Hi there, I am Harry Roberts. I am a 21 year old web developer from the UK. I Tweet and write about web standards, typography, best practices and everything in between. You should browse and search my archives and follow me on Twitter, 7,791 people do.

via Ad Packs