Simple Responsive Accordion With Pure CSS (Free Download)

Welcome to a tutorial on how to create a simple responsive accordion. Yes, there are a lot of “accordion plugins” in the world, but some of them require a third-party framework. It simply does not make sense to load an entire library for a single accordion – So here it is, a super lightweight accordion using only pure CSS. Read on!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

QUICK SLIDES

 

TABLE OF CONTENTS

Download & Notes CSS Accordion Useful Bits
The End

 

DOWNLOAD & NOTES

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

EXAMPLE CODE DOWNLOAD

Click here to download all the source code in a zip file – I have released it under the MIT License, so feel free to build on top of it if you want to.

 

 

CSS ACCORDION

All right, let us now get into creating an accordion using pure HTML and CSS.

 

1) CHECKBOX ACCORDION

1A) THE DEMO

 

1B) THE HTML

1-accordion.html
<!-- FIRST TAB -->
<div class="tab">
  <input id="tab-1" type="checkbox">
  <label for="tab-1">Tab 1</label>
  <div class="content"><p>Next to the risk dictates a nurse.</p></div>
</div>

<!-- SECOND TAB -->
<div class="tab">
  <input id="tab-2" type="checkbox">
  <label for="tab-2">Tab 2</label>
  <div class="content"><p>Should the pace attack?</p></div>
</div>

<!-- THIRD TAB -->
<div class="tab">
  <input id="tab-3" type="checkbox">
  <label for="tab-3">Tab 3</label>
  <div class="content"><p>A circumstance strikes a deserved trap.</p></div>
</div>

The HTML should be straightforward enough.

  • Create a <div class="tab"> container.
  • Sandwich 3 things inside the container.
    • <input id="tab-N" type="checkbox"> Required to toggle show/hide the tab contents.
    • <label for="tab-N"> The tab label itself.
    • <div class="content"> The tab contents.
  • That’s all. Create as many <div class="tab"> sections as required.

 

 

1C) THE CSS

1-accordion.css
/* (A) TABS CONTAINER */
.tab, .tab * {
  font-family: arial, sans-serif;
  box-sizing: border-box;
}
.tab { max-width: 600px; }

/* (B) HIDE CHECKBOX */
.tab input { display: none; }

/* (C) TAB LABEL */
.tab label {
  /* (C1) DIMENSIONS */
  position: relative; /* required for (f2) position:absolute */
  display: block;
  width: 100%;
  margin-top: 10px;
  padding: 10px;
 
  /* (C2) COSMETICS */
  font-weight: 700;
  color: #fff;
  background: #2d5faf;
  cursor: pointer;
}

/* (D) TAB CONTENT - HIDDEN BY DEFAULT */
/* css animation will not work with auto height */
/* this is why we use max-height instead */
.tab .content {
  background: #ccdef9;
  overflow: hidden;
  transition: max-height 0.3s;
  max-height: 0;
}
.tab .content p { padding: 10px; }

/* (E) OPEN TAB ON CHECKED */
.tab input:checked ~ .content { max-height: 100vh; }

/* (F) EXTRA - ADD ARROW INDICATOR */
.tab label::after {
  /* (F1) RIGHT ARROW */
  display: block;  
  content: "\25b6";
 
  /* (F2) PLACE AT RIGHT SIDE */
  position: absolute;
  right: 10px; top: 10px;
 
  /* (F3) ANIMATED ARROW */
  transition: all 0.4s;
}
 
/* (F4) ROTATE ARROW ON CHECKED */
.tab input:checked ~ label::after { transform: rotate(90deg); }

This may look complicated, but the essential mechanics are:

  • (B) First, hide the ugly checkbox with .tab input { display: none; }. The checkbox will still function when we click on the label.
  • (D) Hide the tab contents by default – .tab .content { max-height: 0 }
  • (E) Show the tab contents when the checkbox is checked (when we click on the label) – .tab input:checked ~ .content { max-height: 100vh; }.

Yep, that’s all. The rest is pretty much just cosmetics.

 

 

2) RADIO BUTTON ACCORDION

2A) THE DEMO

 

2B) THE HTML

2-radio.html
<!-- FIRST TAB -->
<div class="tab">
  <input id="tab-1r" type="radio" name="tabr">
  <label for="tab-1r">Tab 1</label>
  <div class="content"><p>Next to the risk dictates a nurse.</p></div>
</div>

<!-- SECOND TAB -->
<div class="tab">
  <input id="tab-2r" type="radio" name="tabr">
  <label for="tab-2r">Tab 2</label>
  <div class="content"><p>Should the pace attack? </p></div>
</div>

<!-- THIRD TAB -->
<div class="tab">
  <input id="tab-3r" type="radio" name="tabr">
  <label for="tab-3r">Tab 3</label>
  <div class="content"><p>A circumstance strikes a deserved trap.</p></div>
</div>

Look no further, the only difference here is that we are using radio buttons and not checkboxes – This will enforce “only one tab can be opened at a time” for those who need it.

 

 

USEFUL BITS

That’s all for this guide, and here is a small section on some extras that may be useful to you.

 

OPENING TABS “BY DEFAULT”

How do we set a tab to be opened on page load? Very simply set the checked attribute – <input type="checkbox" checked>.

 

RADIO ACCORDION RESTRICTION

Well, as some may have already noticed. The default behavior in HTML is that one radio button will be selected at all times, and there is no way we can unselect without using Javascript. So yes, the “restriction” in the radio button accordion is that one tab will be opened at all times.

 

LINKS & REFERENCES

 

YOUTUBE TUTORIAL

 

INFOGRAPHIC CHEAT SHEET

Pure CSS Accordion (click to enlarge)

 

THE END

Thank you for reading, and We have come to the end of this guide. I hope that it has helped you to create a better website, and if you have anything to share with this guide, please feel free to comment below. Good luck and happy coding!

14 thoughts on “Simple Responsive Accordion With Pure CSS (Free Download)”

  1. It might be a very stupid question but since i can´t code at all i´ll go ahead and ask.
    How can I use this on wordpress? I thought about adding the CSS in additional css in the customizer and add the tab class to a paragraph in gutenberg, but I´m pretty sure that´s not going to work because there would be no connection between the title and the content and between the titles and content and the other titles and content… In other words I don´t know where to put the html on wordpress

  2. Hi W.S.,

    Thank you for the code/tutorial! If I wanted to move the arrow pointer to the left, how do I account for the heading text?

    I changed the (F) section “right: 10px” to “left:10px”, which got the arrow on the correct side I want it to show on, but I don’t know how to fix the overlap it has with my tab title text.

    Thank you!
    Sylvia

  3. Thanks again for this. It is great. I have noticed an odd quirk perhaps. For the radio – one at a time drop-downs there seems to be an issue with scrolling when viewing on small screens so that sometimes when you click on a tab, the browser scrolls too far and you have to manually scroll back up to read the contents of the tab. Here is what I did to replicate which might explain better:
    1) Include lots of paragraphs of text in each drop-down.
    2) Include a few paragraphs of text after the drop-down (that is, paragraphs under the drop-down)
    3) Click Tab 1. It displays fine.
    4) Scroll down to Tab 2 and click Tab 2. It displays fine.
    5) Scroll down to Tab 3 and click Tab 3. The browser scrolls down too far and you have to scroll back up to view the start of the text in Tab 3.

    This only occurs on small sized screens. This behaviour does not occur on larger screens. I am not sure what causes it. Maybe there is a limitation on the amount of content you can include in a tab maybe?

    1. Well, you kind of already answered your own question. That is a browser behavior and that is just the way how it renders the HTML/CSS… More CSS probably won’t fix anything. I will limit the content, or use Javascript to listen to the animationend event, then scroll back up automatically.

  4. Thanks so much for this.
    One thing, though. I found that the absolute positioning of the label icon produced undesirable results. The icon – I chose plus and minus for this – was positioned to the edge of the window.
    I fixed this by making the label element a flexbox.
    Thanks again.

  5. Thank you for this tutorial! You saved me a lot of time and headache!! So many accordions require JS, and I’m excited to have found one that doesn’t.

  6. This is fantastic. I was using a javscript version, but this is working better. One quick question, for the radio button options, if I click Tab 1 to expand, is there any way I can click Tab 1 again to collapse it?

  7. Nice! I’ve been looking for an accordion solution that doesn’t include Javascript which clean and simple. Is there an way to set, by default, one of the tabs to be open? Thanks in advance!
    Jake

Leave a Comment

Your email address will not be published.