DEV Community

Cover image for A simple Accordion Menu Using HTML, CSS and JavaScript.
Ryan
Ryan

Posted on

A simple Accordion Menu Using HTML, CSS and JavaScript.

Hey awesome devs. Let's have a look at how we can create a simple accordion menu using HTML, CSS and just a few lines of JavaScript. Let's get started with the HTML.

First, create a div with the class of container

<div class="container">
</div>

Within this div, let's add a paragraph and give it a class of title.

<div class="container">
<p class="title">Do you accept online payements?</p>
</div>

Also, within the same container div, add another paragraph and give it a class of content. Fill this paragraph with some dummy text.

Copy the above two paragraph tags, and paste them two more times, so that you have 3 pairs of paragraph tags.

Finally, inside our paragraphs with the class of title, add a span tag, which contains a + sign . This sign will change to - when clicked by the user on the corresponding title. Below is what your HTML code should look like by now.

<div class="container">
  <p class="title">Do you accept online payements?<span>+</span></p>
  <p class="content">Lorem ipsum dolor, sit amet consectetur 
  adipisicing elit....</p>
  <p class="title">Do you have a return policy?<span>+</span></p>
  <p class="content">Lorem ipsum dolor, sit amet consectetur 
  adipisicing elit....</p>
  <p class="title">What is the average delivery time?<span>+</span></p>
  <p class="content">Lorem ipsum dolor, sit amet consectetur 
  adipisicing elit....</p>
</div>

And that's all we need for the HTML. Now, let's get started with the CSS by first adding some basic reset.

*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

Add the below styles to the body and the div with the class of container.

body{
  background-color: #2BBA9E;
  font-family: Verdana;
}

.container{
  width: 80%;
  margin: 0 auto;
  background-color: #fff;
  margin-top: 10%;
}

Add styles to the paragraphs which have the class of title and content

.title{
  background-color: #202D3C;
  padding: .8rem;
  border-bottom: 1px solid #000;
  cursor: pointer;
  position: relative;
  user-select: none;
  color: #fff;
  letter-spacing: .1rem;
}

.content{
  padding: 1rem;
  line-height: 1.5rem;
  display: none;
}

In the above code, notice that we have given display: none to the paragraphs with the class of content. Now, all you can see are the titles of the accordion menu. Later we will be changing the display to block using a class, which will be added with the help of JavaScript.

At last, we need to style the span which contains the + sign.

span{
  position: absolute;
  right: 1rem;
}

And this is what we have so far.
Alt Text

Now, it's time to move to the most crucial part, the JavaScript.
First select all the paragraphs with the class of title and save these to a variable.

let title = document.querySelectorAll(".title");

Let's use a for loop to loop over each of these.

for(let i = 0; i < title.length; i++){
}

Add an event listener of click to each of them.

for(let i = 0; i < title.length; i++){
title[i].addEventListener("click", function(){
 })
}

Now, we need to select the specific content, which corresponds to the title that the user clicks. For this, we will be using the nextElementSibling property. So, here's what it would look like.
this.nextElementSibling

Of course, understanding the this keyword can be a bit tricky. But, just keep in mind that in this case, the this keyword refers to the title that the user clicks on.

Let's save the above line of code to a variable named result. And, here's the code we have so far.

for(let i = 0; i < title.length; i++){
title[i].addEventListener("click", function(){
  let result = this.nextElementSibling;
 })
}

For our accordion to work, we just need one more line of code. Remember we had given the paragraphs with the class of content a display of 'none'? Well, it's time to change the display to block when the user clicks on a corresponding title.

Create a CSS class of active and add a single property of display: block.

.active{
  display: block;
}

Using the classList property, let's add the active class to paragraphs with the class of content, so that it is displayed as block. However, when the user clicks on it again, we want to change the display back to none. So, we will be using classList.toggle.

for(let i = 0; i < title.length; i++){
  title[i].addEventListener("click", function(){
    let result = this.nextElementSibling;
    result.classList.toggle("active");
  })
}

And we are almost done. The only thing that we need to work on now is the span which contains the + sign. The idea is simple. The + sign will be shown when the content is hidden, and will be replaced with a - sign when the content is shown. We can use the if statement to do the same.

So, our final JavaScript code will look like.

let title = document.querySelectorAll(".title");

for(let i = 0; i < title.length; i++){
  title[i].addEventListener("click", function(){
    let result = this.nextElementSibling;
    result.classList.toggle("active");

     if(this.firstElementChild.innerText === "+"){
       this.firstElementChild.innerText = "-"
       }
    else{
      this.firstElementChild.innerText = "+"
    }

  })
}

And that's how you create a simple accordion menu using HTML, CSS and just a little bit of JavaScript. Hope you like it.

Top comments (9)

Collapse
 
jenuaz profile image
Yevhenii

What do you think is it possible to write the same without JS? :)

Collapse
 
ryandsouza13 profile image
Ryan

Yes, the same can be achieved in pure CSS by using the checkbox hack, which mimics the click event. But, according to expert Devs, it would be wise to refrain from using this method, as it can cause accessibility issues.

Collapse
 
jenuaz profile image
Yevhenii

Can you give me a reference to that expert article ? I will be appreciated!

Thread Thread
 
ryandsouza13 profile image
Ryan

Hi buddy. It wasn't an article that I came across, but several tweets suggesting that a CSS checkbox hack is most likely to cause an issue when it comes to accessibility. But, here's a Quora link I found, which may help.
quora.com/Is-the-CSS-checkbox-hack...
The question in the above link has 2 answers. Make sure to go through both of them. This will give you a better understanding of 2 different perspectives.

A couple of years ago, I did use this technique, but later stopped doing so. Let me know if the above link helped.

Thread Thread
 
jenuaz profile image
Yevhenii • Edited

Thanks. I read those answers on Quora. I didn't get a point about "accessibility issues". I wrote the menu sandwich in pure CSS. And I can't understand why they saying that using JS is much better then write pretty few rows of css. What I think that when you use JS your web browser need to download libraries to work with JS right ? And One class can contain a lot of code. So if we allocate memory for one var which is one Class with all methods and use only one method it's mean that we need much more space to use for that variable instead of writing few rows of css. Maybe I'm wrong I'm not a specialist in this area. But menu written in JS seems to work slower than CSS.
Here is my menu:
codepen.io/jenuaz-the-lessful/pen/...
Can you explain more specific the issue with access issues?

Thread Thread
 
ryandsouza13 profile image
Ryan

Perfectly valid points. But, what if some of our website visitors use screen reader. Of course, screen readers are most likely to ignore elements that have been given a display of none. But, again not 100 % sure about that. Also, tabbing between elements using a keyboard should also be considered as one of the preferred methods of navigating on a webpage.
One good reason to use the checkbox hack would be for users who have disabled JavaScript in the browser.

Thread Thread
 
jenuaz profile image
Yevhenii

Thanks a lot for your explanation ! Very helpful ! I even didn't think about this cases: screen reader, and tabbing between elements using a keyboard.

Thread Thread
 
ryandsouza13 profile image
Ryan

Glad it helped. Have an awesome day ahead.

Thread Thread
 
jenuaz profile image
Yevhenii

U2 :) ! Hope you will continue to write articles like this one :)