Creating an Accordion with HTML, CSS & jQuery

An accordion is usually associated with FAQ areas. If printed to the page, FAQs could stop users from finding the answers they’re after due to all the text they’re presented with.

That’s a good argument as they show a simple outline of the content. Imagine browsing an FAQ and you had to scroll all the way down through loads of sections to find the answer, it would be a painful. If you could simply scroll the titles and have the content hidden, it would allow you to scan much faster, therefore giving a better experience.

You might also like: Creating Tabs with HTML, CSS & jQuery

Table of Contents

  1. Skip to The HTML
  2. Skip to The CSS
  3. Skip to The jQuery

Final result: Coded accordion with HTML, CSS and jQuery


1.) The HTML Structure

Finished HTML

When coding up components I like to follow the BEM structure. Some of you will notice it’s not actual BEM. That’s because I follow a basic principle which uses nested-naming. For example, the entire element has an .accordion-section inside it, which is then followed by an .accordion-section-title.

This approach can have its drawbacks, yet I’ve found it to be sustainable on larger projects because it makes me think about how many elements I’m nesting and if it’s necessary.

It also keeps my Sass organised, therefore it avoids too much nesting and keeps things readable.

<div class="accordion">
	<div class="accordion-section">
		<a class="accordion-section-title" href="#accordion-1">Accordion Section #1</a>

		<div id="accordion-1" class="accordion-section-content">
			<p>Mauris interdum fringilla augue vitae tincidunt. Curabitur vitae tortor id eros euismod ultrices. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent nulla mi, rutrum ut feugiat at, vestibulum ut neque? Cras tincidunt enim vel aliquet facilisis. Duis congue ullamcorper vehicula. Proin nunc lacus, semper sit amet elit sit amet, aliquet pulvinar erat. Nunc pretium quis sapien eu rhoncus. Suspendisse ornare gravida mi, et placerat tellus tempor vitae.</p>
		</div><!--end .accordion-section-content-->
	</div><!--end .accordion-section-->
</div><!--end .accordion-->

2.) The CSS Styling

Finished CSS

There are a few things going on here. First of all, see the overflow:hidden; on the main element. This is done to give the rounded corners effect on the sections, yet stop things hanging over the edge.

I’ve used comments to indicate where any type styling is placed. I do this on all projects to keep things organised. In Sass, I write it as // Type. When you leave a code comment in a Sass file with the two slashes it doesn’t show up in the compiled CSS.

/*----- Accordion -----*/
.accordion,
.accordion * {
	-webkit-box-sizing:border-box;
	-moz-box-sizing:border-box;
	box-sizing:border-box;
}

.accordion {
	overflow:hidden;
	box-shadow:0px 1px 3px rgba(0,0,0,0.25);
	border-radius:3px;
	background:#f7f7f7;
}

/*----- Section Titles -----*/
.accordion-section-title {
	width:100%;
	padding:15px;
	display:inline-block;
	border-bottom:1px solid #1a1a1a;
	background:#333;
	transition:all linear 0.15s;
	/* Type */
	font-size:1.200em;
	text-shadow:0px 1px 0px #1a1a1a;
	color:#fff;
}

.accordion-section-title.active,
.accordion-section-title:hover {
	background:#4c4c4c;
	/* Type */
	text-decoration:none;
}

.accordion-section:last-child .accordion-section-title {
	border-bottom:none;
}

/*----- Section Content -----*/
.accordion-section-content {
	padding:15px;
	display:none;
}

3.) The jQuery Functionality

Finished jQuery

$(document).ready(function() {
	function close_accordion_section() {
		$('.accordion .accordion-section-title').removeClass('active');
		$('.accordion .accordion-section-content').slideUp(300).removeClass('open');
	}

	$('.accordion-section-title').click(function(e) {
		// Grab current anchor value
		var currentAttrValue = $(this).attr('href');

		if($(e.target).is('.active')) {
			close_accordion_section();
		}else {
			close_accordion_section();

			// Add active class to section title
			$(this).addClass('active');
			// Open up the hidden content panel
			$('.accordion ' + currentAttrValue).slideDown(300).addClass('open');
		}

		e.preventDefault();
	});
});

Code Outline/Setup

It’s a best practice to outline the code you’re going to write before you start, especially with something like JS.

Here is the code we need and in this case, we would write it out in a procedural fashion, then move on to making it more modular. As a result, we get the following two examples:

$(document).ready(function() {
	function close_accordion_section() {
		// Close everything up
	}

	$('.accordion-section-title').click(function() {
		// Grab current anchor value
		var currentAttrValue = $(this).attr('href');

		// Open and close here
	});
});
$('.accordion-section-title').click(function() {
	// Grab current anchor value
	var currentAttrValue = $(this).attr('href');

	$('.accordion .accordion-section-title').removeClass('active');
	$('.accordion .accordion-section-content').slideUp(300).removeClass('open');

	$(this).addClass('active');
	$('.accordion ' + currentAttrValue).slideDown(300).addClass('open');
});

From there we can move on to the modular version of the code by adding functions and so on:

function close_accordion_section() {
	$('.accordion .accordion-section-title').removeClass('active');
	$('.accordion .accordion-section-content').slideUp(300).removeClass('open');
}

Accordion Conclusion

In conclusion, they can be very useful, as I said in the intro. However, be aware they should only be used in cases where they’re beneficial, as is the case with any component.

By improving your code as you go, you’ll learn to just make it modular from the start.

If you have any questions or comments just leave a comment below!

You might also like: Create a Fading Popup Modal with jQuery


Comments

Leave a Comment

Comments (195)

Awesome

April 9, 2019 at 8:04 pm

Really great! The best script / solution out there! Thanks so much Seb!

Reply

Subhrahtoti

December 15, 2017 at 4:00 pm

I have one Panel having two child panel which is showing by default.
My requirement is to show only one different panel under main panel if java variable showTwopanel =true else show only one panel.

Reply

Kate

October 17, 2017 at 10:43 am


$(document).ready(function() {
$(‘.accordion .accordion-section:first-child .accordion-section-title’).addClass(‘first’);
function close_accordion_section() {
$(‘.accordion .accordion-section:first-child .accordion-section-title’).removeClass(‘first’);
$(‘.accordion .accordion-section-title’).removeClass(‘active’);
$(‘.accordion .accordion-section-content’).slideUp(300).removeClass(‘open’);
}

$(‘.accordion-section-title’).click(function(e) {
// Grab current anchor value
var currentAttrValue = $(this).attr(‘href’);

if($(e.target).is(‘.active’)) {
close_accordion_section();
}else {
close_accordion_section();

// Add active class to section title
$(this).addClass(‘active’);
$(this).removeClass(‘first’);
// Open up the hidden content panel
$(‘.accordion ‘ + currentAttrValue).slideDown(300).addClass(‘open’);
}

e.preventDefault();
});

Reply

Michael

October 16, 2017 at 6:31 am

I may be missing something but the class “open” doesn’t appear in either the markup and is not defined in the CSS. Could someone please explain how that works. Thanks.

Reply

Brandon

September 28, 2017 at 1:32 pm

For those wondering (like me!) how to get one accordion section to be open on initial page load, take Alex’s improved JS and add a couple lines to the end:

<br />
function close_accordion_section() {<br />
    $(‘.accordion .accordion-section-title’).removeClass(‘active’);<br />
    $(‘.accordion .accordion-section-content’).slideUp(300).removeClass(‘open’);<br />
}</p>
<p>$(‘.accordion-section-title’).on(‘click’, function(e){<br />
        e.preventDefault();<br />
        var currentAttrValue = $(this).next();</p>
<p>        if($(this).is(‘.active’)) {<br />
            close_accordion_section();<br />
        }<br />
        else {<br />
            close_accordion_section();<br />
            $(this).addClass(‘active’);<br />
            $(currentAttrValue).slideDown(300).addClass(‘open’);<br />
        }<br />
});</p>
<p>// Activate first accordion item on page load. Change CSS selector as needed to work with your own HTML structure.<br />
$(‘.accordion:first-child .accordion-section-title’).addClass(‘active’);<br />
$(‘.accordion:first-child .accordion-section-content’).slideDown(0).addClass(‘open’);<br />
Reply

jos

September 26, 2017 at 7:04 pm

Opens the first!
$( document ).ready(function() {
$(‘a[href$=”#accordion-1″]’).click();

});

Reply

Robert

January 25, 2018 at 6:11 am

your code worked!!!

Reply

Nilam

May 11, 2017 at 2:00 pm

Hello
I want show default open one accordion when page is load .How I can do this.
please as soon as possible.
Thank you.

Reply

Mike

March 20, 2017 at 2:34 pm

How could I open one ore more accordions by default?
Thanks in advance

Reply

Alex

March 9, 2017 at 10:33 am

Hi, everybody!
Some impovements.
If you don’t want to manually assign id=”accordion-1″, id=”accordion-2″, etc… to the DIV with classname=”accordion-section-content”.
Just take this script:


function close_accordion_section() {
$(‘.accordion .accordion-section-title’).removeClass(‘active’);
$(‘.accordion .accordion-section-content’).slideUp(300).removeClass(‘open’);
}

$(‘.accordion-section-title’).on(‘click’, function(e){
e.preventDefault();
var currentAttrValue = $(this).next();

if($(this).is(‘.active’)) {
close_accordion_section();
}
else {
close_accordion_section();
$(this).addClass(‘active’);
$(currentAttrValue).slideDown(300).addClass(‘open’);
}
});

Reply

Florin

September 18, 2018 at 9:39 pm

THANK YOU FOR THIS!

Reply

Rajesh

October 17, 2016 at 10:13 am

How to get the first accordion element open by default??

Reply

anmol

July 22, 2017 at 11:23 am

Sir Please tell me how i could 1st accordian be opende by default when page is refreshed

Reply

Jen

October 2, 2016 at 5:51 pm

I’ve been trying to figure out a way to make the default of the accordion as open. Is there a way?

Reply

Dave

September 8, 2016 at 8:46 pm

Hey everyone,

I, too, was confused about the sections opening and closing together. To fix this you have to rename your accordions in your HTML numerically. Example:

<br />
&lt;div class=&quot;accordion&quot;&gt;<br />
    &lt;div class=&quot;accordion-section&quot;&gt;<br />
        &lt;a class=&quot;accordion-section-title&quot; href=&quot;#accordion-1&quot;&gt;View Source&lt;/a&gt;</p>
<p>        &lt;div id=&quot;accordion-1&quot; class=&quot;accordion-section-content&quot;&gt;<br />
            &lt;p&gt;Mauris interdum fringilla augue vitae tincidunt. Curabitur vitae tortor id eros euismod ultrices. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent nulla mi, rutrum ut feugiat at, vestibulum ut neque? Cras tincidunt enim vel aliquet facilisis. Duis congue ullamcorper vehicula. Proin nunc lacus, semper sit amet elit sit amet, aliquet pulvinar erat. Nunc pretium quis sapien eu rhoncus. Suspendisse ornare gravida mi, et placerat tellus tempor vitae.&lt;/p&gt;<br />
        &lt;/div&gt;&lt;!–end .accordion-section-content–&gt;<br />
    &lt;/div&gt;&lt;!–end .accordion-section–&gt;<br />
&lt;/div&gt;&lt;!–end .accordion–&gt;<br />

On the next accordion rename your href and div id to accordion-2. That’s it. Hope that helped!

Reply

Victor M. Barba

August 21, 2016 at 10:38 pm

Hello:
I hope you can help me. I would like to make some improvements to my web-site. songnes.com How much would you charge me, to make a contact form that actually “works” with only HTML and CSS. If you my web-site I don’t have a contact form.
I hope I hear back from you… Thanks
Victor

Reply

anu

August 9, 2016 at 10:20 am

Thanks for the demo . I should have only one accordian opened at a time ,it does that job ..but when i try to close the current accordian ,it toggles instead of closing the content ..help required pls !!

Reply

Adrien Rosi

June 23, 2016 at 11:26 am

An other way :

<br />
&lt;ul class=&quot;accordion&quot;&gt;<br />
	&lt;li&gt;<br />
		&lt;ul&gt;<br />
			&lt;li&gt;Title&lt;/li&gt;<br />
			&lt;li&gt;Notre volonté est de promouvoir la rénovation énergétique dite &quot;à coût zéro&quot;. Cela signifie que les économies d’énergie réalisées par les travaux d’isolation couvrent le coût des ouvrages, financé par l’éco-prêt à taux zéro.&lt;/li&gt;<br />
		&lt;/ul&gt;<br />
	&lt;/li&gt;<br />
	&lt;li&gt;<br />
		&lt;ul&gt;<br />
			&lt;li&gt;Title&lt;/li&gt;<br />
			&lt;li&gt;Notre volonté est de promouvoir la rénovation énergétique dite &quot;à coût zéro&quot;. Cela signifie que les économies d’énergie réalisées par les travaux d’isolation couvrent le coût des ouvrages, financé par l’éco-prêt à taux zéro.&lt;/li&gt;<br />
		&lt;/ul&gt;<br />
	&lt;/li&gt;<br />
	&lt;li&gt;<br />
		&lt;ul&gt;<br />
			&lt;li&gt;Title&lt;/li&gt;<br />
			&lt;li&gt;Notre volonté est de promouvoir la rénovation énergétique dite &quot;à coût zéro&quot;. Cela signifie que les économies d’énergie réalisées par les travaux d’isolation couvrent le coût des ouvrages, financé par l’éco-prêt à taux zéro.&lt;/li&gt;<br />
		&lt;/ul&gt;<br />
	&lt;/li&gt;<br />
	&lt;li&gt;<br />
		&lt;ul&gt;<br />
			&lt;li&gt;Title&lt;/li&gt;<br />
			&lt;li&gt;Notre volonté est de promouvoir la rénovation énergétique dite &quot;à coût zéro&quot;. Cela signifie que les économies d’énergie réalisées par les travaux d’isolation couvrent le coût des ouvrages, financé par l’éco-prêt à taux zéro.&lt;/li&gt;<br />
		&lt;/ul&gt;<br />
	&lt;/li&gt;<br />
&lt;/ul&gt;</p>
<p>&lt;script&gt;<br />
$(document).ready(function(){<br />
	$(‘.accordion&gt;li&gt;ul&gt;li:first-child’).click(function(){<br />
		$(‘.accordion&gt;li&gt;ul&gt;li:last-child’).slideUp();<br />
		$(this).parents().children(‘:last-child’).slideDown();</p>
<p>	});<br />
});<br />
&lt;/script&gt;<br />

Reply

Paul

June 10, 2016 at 1:20 pm

Can you add a expand all and collapse all link with function to the accordion?

Thank you, great tutorial.

Reply

Inspirational Newsletter


Join the newsletter to get the best articles, tutorials and exclusive freebies every two weeks.

No spam. You can unsubscribe at any time.