Elegant Accordion with jQuery and CSS3

Today we will create an elegant accordion for content. The idea is to have some vertical accordion tabs that slide out when hovering. We will add some CSS3 properties to […]

Today we will create an elegant accordion for content. The idea is to have some vertical accordion tabs that slide out when hovering. We will add some CSS3 properties to enhance the looks.
Ok, let’s start with the markup.

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

The HTML will consist of a list where each accordion tab is a list element. Inside of the list element we will have a heading that disappears when we hover. Also, there will an element for the white background gradient and a div for the description. Here is the markup with just one list element:

<ul class="accordion" id="accordion">
	<li class="bg1">
		<div class="heading">Heading</div>
		<div class="bgDescription"></div>
		<div class="description">
			<h2>Heading</h2>
			<p>Some descriptive text</p>
			<a href="#">more ?</a>
		</div>
	</li>
</ul>

The other list elements will have the classes bg2, bg3 and bg4. The unordered list gets a class and an id since we want to address it later in the JavaScript. Of course, we would not really need the class but instead,  style the element using #accordion in our style sheet. But this is a good way to keep things separate.

The CSS

The style for the list will look as follows:

ul.accordion{
    list-style:none;
    position:absolute;
    right:80px;
    top:0px;
    font-family: Cambria, serif;
    font-size: 16px;
    font-style: italic;
    line-height: 1.5em;
}

The list elements will each have a different background image, so we will first define the general style properties for every list element and then the single classes with the background images:

ul.accordion li{
    float:right;
    width:115px;
    height:480px;
    display:block;
    border-right:2px solid #fff;
    border-bottom:2px solid #fff;
    background-color:#fff;
    background-repeat:no-repeat;
    background-position:center center;
    position:relative;
    overflow:hidden;
    cursor:pointer;
    -moz-box-shadow:1px 3px 15px #555;
    -webkit-box-shadow:1px 3px 15px #555;
    box-shadow:1px 3px 15px #555;
}
ul.accordion li.bg1{
    background-image:url(../images/1.jpg);
}
ul.accordion li.bg2{
    background-image:url(../images/2.jpg);
}
ul.accordion li.bg3{
    background-image:url(../images/3.jpg);
}
ul.accordion li.bg4{
    background-image:url(../images/4.jpg);
}

Note, that the box shadow will not work in IE.
The initial width of each item will be 115 pixels. We will alter this in the JavaScript hover function (to 480px).
The border that we give each list element can only be applied to one side, otherwise we would have a double border in between the items and just a single one at the outer limits. So, we need to define a class for a left border, that we will apply to the last list element (they are floating right, so the order is reversed):

ul.accordion li.bleft{
    border-left:2px solid #fff;
}

Now, we want a nice looking header with a white semi-transparent background for each list item when in the normal “closed” state:

ul.accordion li .heading{
    background-color:#fff;
    padding:10px;
    margin-top:60px;
    opacity:0.9;
    text-transform:uppercase;
    font-style:normal;
    font-weight:bold;
    letter-spacing:1px;
    font-size:14px;
    color:#444;
    text-align:center;
    text-shadow:-1px -1px 1px #ccc;
}

The div that contains the description will have the following style:

ul.accordion li .description{
    position:absolute;
    width:480px;
    height:175px;
    bottom:0px;
    left:0px;
    display:none;
}

We set it to display:none initially, since we only want it to appear when hovering. And here is, how we style the inner elements:

ul.accordion li .description h2{
    text-transform:uppercase;
    font-style:normal;
    font-weight:bold;
    letter-spacing:1px;
    font-size:45px;
    color:#444;
    text-align:left;
    margin:0px 0px 15px 20px;
    text-shadow:-1px -1px 1px #ccc;
}
ul.accordion li .description p{
    line-height:14px;
    margin:10px 22px;
    font-family: "Trebuchet MS", sans-serif;
    font-size: 12px;
    font-style: italic;
    font-weight: normal;
    text-transform: none;
    letter-spacing: normal;
    line-height: 1.6em;
}
ul.accordion li .description a{
    position:absolute;
    bottom:5px;
    left:20px;
    text-transform:uppercase;
    font-style:normal;
    font-size:11px;
    text-decoration:none;
    color:#888;
}
ul.accordion li .description a:hover{
    color:#333;
    text-decoration:underline;
}

The only style missing is the one for the gradient element:

ul.accordion li .bgDescription{
    background:transparent url(../images/bgDescription.png) repeat-x top left;
    height:340px;
    position:absolute;
    bottom:0px;
    left:0px;
    width:100%;
    display:none;
}

The image that we are repeating is a gradient that goes from white to transparent. This will give a nice effect when we make this div slide in from the bottom.

Let’s add some magic!

The JavaScript

First, we include the jQuery library before the body end tag:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

Now, we will add a function that makes a list element slide out when hovering over it. This will be achieved by animating the increase of the width to 480 pixels. Then the top heading should fade out while the gradient (css class “bgDescription”) and the description appear:

<script type="text/javascript">
$(function() {
    $('#accordion > li').hover(
        function () {
            var $this = $(this);
            $this.stop().animate({'width':'480px'},500);
            $('.heading',$this).stop(true,true).fadeOut();
            $('.bgDescription',$this).stop(true,true).slideDown(500);
            $('.description',$this).stop(true,true).fadeIn();
        },
        function () {
            var $this = $(this);
            $this.stop().animate({'width':'115px'},1000);
            $('.heading',$this).stop(true,true).fadeIn();
            $('.description',$this).stop(true,true).fadeOut(500);
            $('.bgDescription',$this).stop(true,true).slideUp(700);
        }
    );
});
</script>

The first function inside of $(‘#accordion > li’).hover is the function triggered when the mouse moves over the respective element and the second function gets triggered when moving the mouse out again. Here we reverse the actions and also add some timing to it, so that the elements disappear smoothly.

And that’s all! I hope you enjoyed this tutorial and find it useful!

Message from TestkingWe offer online oracle training program to help you pass pmi certifications on time. Learn about jquery and css3 using security+ tutorial and other resources.

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay in the loop: Get your dose of frontend twice a week

Fresh news, inspo, code demos, and UI animations—zero fluff, all quality. Make your Mondays and Thursdays creative!

Feedback 74

Comments are closed.
  1. great accordion !!!

    little trouble on FF, image appeart and disappeart rapidly on bottom right

    (sorry for my poor english, french inside)

    • Hi Jireck,
      I noticed that in my version of FF it seems to be a bit slower, but the image does not disappear. I was testing with version 3.6.3, which one do you have? Thanks a lot for the comment! Cheers, ML

  2. Hi WEB Family,

    This is the one was looking for, because I´ve used Flash for this but now I´ll follow your instruction.

    Thanks for sharing

    • @dox Which version are you using? Do you run Mac or Win? My version is 4.0.4 on Win and it runs very smoothly. Cheers, ML

  3. @Shua Ok, I tested on Safari 4.0.5 (531.22.7) and it looks just fine. Why exactly is it “unusable” to you? Cheers, ML

  4. Will be trying this on other browsers to see the difference. On my year-old laptop running FF 3.6 they were a bit choppy. Still, nice resource!

  5. Hi great script I will use in next project
    One question – How can i replace “hover” with “onmousedown” event
    It sok when slide open , but closing is problem

    Tnx

  6. Hey…
    @ML :
    I had same Problems like JIRECK.

    It appears when the bowser window is to short for the Accordion.
    At the time – one AccordionElement fade in and another AccordionElement fade out by selecting one of them, the Elements wrap because the width of the Accordion is greater than the Browser window…

    Sorry for my very BAD english O:-)

  7. @Marco I understand the problem now and I would say that you should try to change the timings in the function. You can make it slide back in faster. Or you can try to give the ul a height, let’s say of 480px and then say overflow:hidden. This will hide the nice shadow effect and it looks a little bit jerky, but at least the li elements don’t appear below the accordion. I hope it helps, let me know how it goes.

    @Jireck Sorry I did not understand what you meant, I hope this is useful for you, too! 🙂

    Thanks for your comments,
    cheers, ML

  8. I set it up and am testing the code as is before modifying. Using Firefox, when I mouse over the first (furtherest left) then go to the next, the first one drops below the so both are aligned to the right.

    I would love to use this but only 150px high.

    Great with the CSS.

  9. Spoke too soon, not working well. with the hidden it just isn’t the same.

  10. When i test locally in Firefox and IE the boxes appear tiled vertically until rolled over. After the initial rollover, they work properly. Can you advise?

  11. @ML :
    I test with my FF 3.6.3 at my job and it’s OK, no more trouble.

    I’ll check at home and tell you.

  12. This looks very cool, have used another accordion script, but would like to try this one out next time.
    Thanks

  13. Excellent JQuery 🙂 BUT can it start with the first panel open? If so how?

  14. @David, try this: in the inline style of the li with class bg4 set the width to 480px. Then set the display of the div with class heading to “none” and remove the inline style of the next two divs that say display:none. That should make the first one being open at the beginning. It will close then again once you hover over the li elements. I am not sure if it’s what you want. Let me know, cheers, ML

  15. @MARY LOU

    GREAT EFFECT!!! THANKY YOU VERY MUCH!!!!

    I want to expand the accordion with 8 elements with a width of 960px and a height of 480px.

    My problem ist, that the “on hover effect” slides the elements on the bottom and returns

    How can I have smooth slide effect without the “bottom effect”?

    Once again: BIG THANX for this slider!!!

    Thank you

  16. It Amazing. I intend to write a Joomla module based on it!
    A question: Is it possible to have one of the strip open from the beginning?
    It will make the width constant! and this is important in some site!

  17. Very Cool Mary Lou, I have the same question as
    tunnel maker’s post on June 22nd, 2010 at 23:22

    I want to expand the accordion with 8 elements with a width of 960px and a height of 480px.

    My problem ist, that the “on hover effect” slides the elements on the bottom and returns

    How can I have smooth slide effect without the “bottom effect”?

    Once again: BIG THANX for this slider!!!

    Thank you

    @MARY LOU

    GREAT EFFECT!!! THANKY YOU VERY MUCH!!!!

  18. tunnel maker, use
    position:relative;
    in ul.accordion

    No sliding to the bottom or carrying over.

    I hope this helps someone.

  19. Hi, thanks for a great tut!

    Just wondering if it is possible to squeeze the rest of the images together (to like 80px instead of the original 115px) while hoovering one of them. an example of what i mean http://ticketcake.com/

  20. Hi and thanks alot for this!

    Is it possible to always have one element open? so that the width is consistant

  21. This is a fantastic tutorial, thank you for putting it up Mary Lou. It’s great to see queries being answered as well.

    If I may (as with others above) I would like to know how to make the width static and the hover movements contained within that static width.

    Thank you so much.

  22. hi.. it’s a verry cool menu, but i was trying to make the first “slide” to stay open at the beggining & tried out what u recomended b4 but it doesn’t seem to work for me 🙁
    any suggestions??

  23. That look’s great.
    But i’m not able to use it perfectly.
    Does someone can help me?
    Can someone can explain to a real motivate guy how to use it?

    I use some CMS, so I can use Html and Java, but I don’t know where to change the CSS…..

    Please help me !!!! 🙂

  24. Great work! However, its floating to the top of my page. How can I get it to stay where I need it to be on the page? Thanks for the help.

  25. Awesome script!
    only having some problems with the images themselfs, because i wanted to change the width of de images when they’re expand, because my images are smaller, i cant seem to figuere out how to change that. If somebody could help me, that would be great!

  26. hi

    I love the script! Is it possible to add a click function rather than a hover

    Thank you

    JC

  27. Hi!
    Thanks for this great tutorial!

    I wonder, can I make the first li to already slide out when the page loaded? Only the first li will have a full initial width.

    Hope you can understand what I meant. Sorry for bad english here.

    Regards,
    Egar

  28. hey can i use this am a newbie to jquery and this just caught my attention, this is some really cool stuff you are doing, things i didnt think possible with javascript

  29. great script!!!

    i have expanded the amount of elements to 8 and now i want to squeeze the inactive elements to keep a total width of 980px. but my accordion splits and the elements above 980px are shown below.

    can you give me a hint???

  30. got it!!!!

    but now the accordion gets squeezed when i dont have the mouse on. i want to have one element keeps open.

  31. It’s great to see how powerful of what jquery can do over flash. Please i do i make the tutorial to expand slide upward. have tried to make it but each time i try it slide downward from the top, i want to it slide upward from bottom.

  32. it’s a great script but i want the first panel opened everytime not only at the beginning. I saw ur answer to dave but it’s only for the beginning.

  33. Love the beauty of this accordion, but does anyone know how to modify the jquery so the unopened panels squeeze smaller when one of the other panels is opened? Thus, the defined width of the entire accordion stays finite. I have set this up for a defined width of 960px with 6 images. When none of the images are opened, each accordion image has a width of 160px. When an image is opened, it opens to a width of 600px, which should squeeze the remaining 5 images to a width of 72px each. I have seen other accordion menus do this, but I can’t figure out how to make that change to the code myself. Any ideas?

  34. Just wanted to say thanks again for posting your Elegant Accordion code.

    I combined techniques from your Elegant Accordion with Jeremy Martin’s Kwicks Accordion and got what I wanted … an accordion image menu which maintains a constant width. My finished accordion can be seen at http://www.jenniferhoffdavis.com/BalletTemplate.

  35. How to make starting slide to show by default. present all the slides are in hidden position. I want by default first slide open.
    Also, how to increase the width of the sliding menu.