Create CSS Accordion without JavaScript

Nowadays, most of web page assets can be created without using JavaScript. Yup! you heard it right, whether you are creating menu navigation or image slider you can functionalize it using pure CSS. Similarly, you can also build a responsive accordion with CSS without using JavaScript/jQuery.

So, today we are going to build a multi-level accordion that can be used for the FAQs page. Likewise, it can be also used in MCQs or as a general-purpose content accordion. Anyhow, it depends upon your project in which you want to implement this accordion.

Before going further, check the live version of the accordion on the demo page if you haven’t checked it. OK! now we’ll build this accordion in HTML and style it using CSS. So, let’s get started!

HTML Structure to Create CSS Accordion

The markup structure of the accordion is a bit complicated. However, we just need to add a group of elements in a sequence. There are two main parts of this FAQs accordion, one of them is question categories and the other one is a container of sub-questions.

There will be an HTML radio input and label tag above each question and answer. We’ll add the toggle function with the help of these radio inputs. All these elements we’ll wrap into the main div element.

So, first of all, create the main div element with a class name “wrap” and define a section for questions. Similarly, add questions and answer just like the below HTML structure:

<div class="wrap">    
    <section class="question-section"> 
        <div class="cat-1">
            <input id="tab-1" type="radio" name="tabs" tabindex="1"> 
            <label for="tab-1" >Technical</label><!-- end of tab label -->

            <div class="question-wrap">
                <div class="question">
                    <input id="question-1" type="radio" name="questions-tab-one" tabindex="2">
                    <label for="question-1" >Your question here</label><!-- end of question label -->
                    <p class="answer answer-1">Put your answer here.</p>
                </div>
                <div class="question"> 
                    <input id="question-2" type="radio" name="questions-tab-one" tabindex="3">
                    <label for="question-2" >What is your second question?</label><!-- end of question label -->
                    <p class="answer answer-2">Give your answer here.</p>
                </div>
                .
                .
                .
                .
            </div>
        </div><!-- end of Catagory -->
        
        <div class="cat-2">
            <input id="tab-2" type="radio" name="tabs" tabindex="7">
            <label for="tab-2" >SassBreak</label>

            <div class="question-wrap">
               <!-- Add your questions according to the above question/answer structure -->
                </div>
            </div>
    
        <div class="cat-3">
            .
            .
            .
            .
            .
        </div>
        <div class="cat-4">
            .
            .
            .
            .
            .
        </div>
    </section><!-- End of Questions -->
</div>

Place the questions markup in cat-3, cat-4, and cat-n respectively.

The CSS Styles

In CSS, we’ll define styles for each element of the accordion. In order to make it responsive, we’ll add CSS media queries to each selector. So, the following are basic styles for the question section. If you want to customize it, you can pass the custom values for background, box-shadow, and font-size, etc.

.question-section {
  background: #ebfdfb;
  box-shadow: 0 2px 5px rgba(68, 68, 68, 0.4);
  display: inline-block;
  font-size: 1rem;
  margin-bottom: 1em;
  padding: 1em;
  position: relative;
  vertical-align: top;
  width: 100%;
}
@media (min-width: 50em) {
  .question-section {
    font-size: .75rem;
    padding: 1em 1.5em;
  }
}
@media (min-width: 62.5em) {
  .question-section {
    font-size: 1rem;
  }
}

Define the styles for the wrapper/outer of the accordion.

.wrap {
  display: block;
  max-width: 1024px;
  margin: 0 auto 2em;
  padding: 0 1em;
  width: 100%;
}
@media (min-width: 43.75em) {
  .wrap {
    padding: 3em;
  }
}

Now add some basic styles for paragraphs, heading, and links of the accordion. These styles are optional, you don’t need to add to your project.

p {
  color: #555;
  text-shadow: 1px 1px 1px #fff;
}

a, a:visited {
  color: #4bc5b7;
  text-decoration: none;
}
.question-section h1 {
  font-family: "Audiowide", cursive;
  color: #085078;
  font-size: 1.25em;
  font-size: 5.5vw;
  font-weight: 700;
  margin-bottom: .25em;
}
@media (min-width: 32.25em) {
  .question-section h1 {
    font-size: 2.25em;
    font-size: 4.9vw;
  }
}
@media (min-width: 67.5em) {
  .question-section h1 {
    font-size: 3.25em;
  }
}
.question-section > p, .question-section > h1 {
  text-align: center;
}
.question-section > p {
  font-size: 0.667em;
  font-size: 2.8vw;
  margin-bottom: 1em;
}
@media (min-width: 22.1875em) {
  .question-section > p {
    font-size: 0.667em;
  }
}
@media (min-width: 31.25em) {
  .question-section > p {
    font-size: 1em;
  }
}
@media (min-width: 81.25em) {
  .question-section > p {
    font-size: 1.15em;
  }
}

Add the following CSS for question categories and label styles. These styles will produce visible (and clickable) title of a question. If you want to customize it, you can change its background (that is #72d2c6) and text color.

div[class^="cat"] {
  width: 100%;
}
div[class^="cat"] > label {
  background: #72d2c6;
  color: #fff;
  cursor: pointer;
  display: block;
  font-weight: bold;
  line-height: 1.4;
  margin-bottom: 0.5em;
  padding: 0.75em 0.5em;
  -webkit-transition: all 0.55s;
  transition: all 0.55s;
}
div[class^="cat"] > label:hover {
  background: #85D8CE;
}
@media (min-width: 50em) {
  div[class^="cat"] > label {
    font-size: 1.25em;
  }
}
div[class^="cat"] > input {
  position: absolute;
  z-index: -999;
}
div[class^="cat"] > input:focus + label {
  background: #4bc5b7;
  letter-spacing: 1px;
}
div[class^="cat"] .question-wrap {
  height: 100%;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  -webkit-transition: all 0.75s cubic-bezier(0.19, 1, 0.22, 1);
  transition: all 0.75s cubic-bezier(0.19, 1, 0.22, 1);
  width: 100%;
}
div[class^="cat"] > input:checked ~ .question-wrap {
  max-height: 1000px;
  opacity: 1;
  -webkit-transition: all 1.95s cubic-bezier(0.19, 1, 0.22, 1);
  transition: all 1.95s cubic-bezier(0.19, 1, 0.22, 1);
}
.question-wrap .question {
  margin: 1em 0;
}
.question-wrap label {
  color: #0a6090;
  cursor: pointer;
  display: block;
  font-weight: bold;
  margin-bottom: 0.5em;
}
@media (min-width: 50em) {
  .question-wrap label {
    font-size: 1.25em;
  }
}

Finally, we’ll hide the default radio input and functionalize the accordion using CSS checked pseudo-selector. If you want to customize the label on focus, you can pass the custom CSS styles in the input:focus {} selector. Likewise, you can increase/decrease toggle speed by setting the custom values for the transition attribute.

.question-wrap input {
  position: absolute;
  z-index: -999;
  top: -10000px;
}
.question-wrap input:focus + label {
  color: #064060;
}
.question-wrap input:not(:checked) ~ p {
  height: 100%;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  -webkit-transition: all 0.75s cubic-bezier(0.19, 1, 0.22, 1);
  transition: all 0.75s cubic-bezier(0.19, 1, 0.22, 1);
}
.question-wrap input:checked ~ p {
  max-height: 500px;
  opacity: 1;
  -webkit-transition: all 1.95s cubic-bezier(0.19, 1, 0.22, 1);
  transition: all 1.95s cubic-bezier(0.19, 1, 0.22, 1);
}

input:focus {
  border: 3px solid red;
  outline: 3px solid red;
  background: red;
}

a:focus {
  color: #085078;
  font-weight: bold;
  outline: none;
}

That’s all! let me know by comment below if you are able to create a pure CSS accordion without using JavaScript.

You Might Be Interested In:

Muhammad Asif is a Front End Developer and Editor Staff at Codeconvey.com. He enjoys experimenting with new CSS features and helping others learn about them.

7 thoughts on “Create CSS Accordion without JavaScript”

  1. 2 Things would be nice for this, 1 – toggle so that if you click on a catagory or question it opens, click again it closes(which it doesnt). 2 – when a question is clicked he page slides up so the question and answer is at the top. It seems when you click a question it sometimes appears at the bottom of the screen out of view and you have to scroll down to see it.

    • Hi Fitzgerald!
      Yes, users need to scroll the page if content out of view.

  2. would is not be beter if it automatically scrolled the section to the top for faster and easier reading?

    • Off course! It will be awesome. It can be done using jQuery, let me provide you the solution. Be with me!

  3. I am actually testing it out using a windows form application and not using a browser at all. So far it works well but it does have some issues using Javascript and jQuery. I was thinking about implementing anchors but was not sure that wold work. However I do like the look of this script you designed, I tip my hat to you on your work 🙂

Comments are closed.