Responsive Accordion In HTML CSS (No Javascript)

Welcome to a tutorial on how to create a simple responsive accordion with HTML and CSS. Yes, you read that right, no Javascript is involved.

To create an accordion using HTML and CSS only:

  • Create a “stack” of checkbox, label, and container.
    • <input id="check" type="checkbox">
    • <label for="check">Title</label>
    • <div id="content">Content</div>
  • Hide the checkbox and content by default. Only show the content when the checkbox is checked.
    • #check, #content { display: none; }
    • #check:checked ~ #content { display : block; }

Yep, that’s all for the basic mechanics. Read on for a “nice example”!

 

 

TABLE OF CONTENTS

 

DOWNLOAD & DEMO

Here is the download link to the example code, so you don’t have to copy-paste everything.

 

EXAMPLE CODE DOWNLOAD

Click here to download | Example on CodePen

The example code is released under the MIT license, so feel free to build on top of it or use it in your own project.

 

SORRY FOR THE ADS...

But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.

Buy Me A Coffee Code Boxx eBooks

 

ACCORDION DEMO

 

 

HTML CSS ACCORDION

All right, let us now get into a slightly more detailed example of the HTML CSS accordion.

 

TUTORIAL VIDEO

 

PART 1) THE HTML

1-accordion.html
<!-- TAB 1 -->
<div class="a-tab">
  <input id="tab-1" class="a-check" type="checkbox">
  <label for="tab-1" class="a-label">Title 1</label>
  <div class="a-content"><img src="pasta.webp"></div>
</div>

<!-- TAB 2 -->
<div class="a-tab">
  <input id="tab-2" class="a-check" type="checkbox">
  <label for="tab-2" class="a-label">Title 2</label>
  <div class="a-content"><img src="pizza.webp"></div>
</div>
  • As in the introduction, we only need to create a “stack” of checkbox, label, and container.
  • The only difference here is that we wrap them in a <div class="a-tab">.

 

 

PART 2) BASIC MECHANICS

1-accordion.css
/* (A) HIDE CHECKBOX & CONTENT */
.a-check { display: none; }
.a-content { max-height: 0; overflow: hidden; }
 
/* (B) SHOW CONTENT ON CHECKED */
.a-check:checked ~ .a-content { max-height: 500px; overflow: auto; }
.a-content { transition: all 0.5s; }

This is a slightly different approach from the introduction snippet.

  • We hide the checkbox with display: none as usual.
  • But hide the content with max-height: 0 and overflow: hidden.
  • The reason is simple, we combine max-height with transition to give a nice “grow and shrink” animation.

 

PART 3) RESPONSIVE & COSMETICS

1-accordion.css
/* (C) COSMETICS */
/* (C1) WRAPPER */
.a-tab { max-width: 600px; }
 
/* (C2) LABEL */
.a-label {
  display: block; width: 100%; padding: 10px;
  font-weight: 700; cursor: pointer;
  color: #fff; background: #2d5faf;
}
 
/* (C3) LABEL ARROW */
.a-label { position: relative; }
.a-label::after {
  display: block; content: "\25b6";
  position: absolute; right: 10px; top: 10px;
  transition: all 0.4s;
}
.a-check:checked ~ label::after { transform: rotate(90deg); }
 
/* (C4) CONTENT */
  .a-check:checked ~ .a-content {
  padding: 10px;
  background: #ccdef9;
}
 
/* (C5) ENTIRE PAGE */
img { width: 100%; }
* {
  font-family: Arial, Helvetica, sans-serif;
  box-sizing: border-box;
}

The rest are pretty much cosmetics. Feel free to change the font, colors, and dimensions.

 

 

EXTRAS

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

 

ONLY ONE TAB CAN OPEN AT A TIME

2-radio.html
<!-- TAB 1 -->
<div class="a-tab">
  <input id="tab-1" name="tab-group" class="a-check" type="radio" checked>
  <label for="tab-1" class="a-label">Title 1</label>
  <div class="a-content"><img src="pasta.webp"></div>
</div>

<!-- TAB 2 -->
<div class="a-tab">
  <input id="tab-2" name="tab-group" class="a-check" type="radio">
  <label for="tab-2" class="a-label">Title 2</label>
  <div class="a-content"><img src="pizza.webp"></div>
</div>

Use radio buttons instead of checkboxes, and set them to the same name.

 

OPENING TABS “BY DEFAULT”

How do we set a tab to be opened by default? 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

 

INFOGRAPHIC CHEAT SHEET

Pure HTML CSS Accordion (click to enlarge)

 

THE END

Thank you for reading, 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!

15 thoughts on “Responsive Accordion In HTML CSS (No Javascript)”

  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.

Leave a Comment

Your email address will not be published. Required fields are marked *