DEV Community

Cover image for How to show the clicked element only and hide others in Vanilla JavaScript?
Mohammed
Mohammed

Posted on

How to show the clicked element only and hide others in Vanilla JavaScript?

I wanted to create this post because I spent a lot of time searching for a solution to this problem and most of the answers I found in Google/StackOverflow was requiring me to use JQuery. I felt like there has to be a post solving this problem in Vanilla JavaScript for those don't want to use any libraries or frameworks. So here's me trying to achieve that.

First, let’s start with the HTML and create a list of buttons.

<div class="selectSection">
 <button type="button" data-number="1" class="active">Button 1</button>
 <button type="button" data-number="2">Button 2</button>
 <button type="button" data-number="3">Button 3</button>
</div>
Enter fullscreen mode Exit fullscreen mode

I gave the first button a class with the name .active so it’s clicked when the page is loaded. The data attribute was used to pair each button with the content that’s related to it. I named it data-number for simplicity. You can use any word & value you like. More info about data attribute.

Now, let’s add the content section and do the same as before with the data attribute:

<div class="contentSection">
   <p class="content" data-number="1">Content of button 1</p>
   <p class="content" data-number="2"> Content of button 2</p>
   <p class="content" data-number="3"> Content of button 3</p>
 </div>
Enter fullscreen mode Exit fullscreen mode

As for the CSS, I will only add this part:

.content:not(:first-child) {
    display: none;
}
Enter fullscreen mode Exit fullscreen mode

What I did was selecting all classes named .content and gave every class except the first a display: none so only the first .content class will show up. This part of CSS alongside with giving the first button a class of .active in HTML work together. If you don’t want the first button and content to show up when the page is loaded, delete this part: :not(:first-child) from the above CSS and remove the class .active from the first button.

Now let’s get to the last part, JavaScript:

// grab all the buttons
let Buttons = document.querySelectorAll(".selectSection button");

// loop through the buttons using for..of 
for (let button of Buttons) {

 // listen for a click event 
 button.addEventListener('click', (e) => {
  // Store the event target in a const
  const et = e.target;

  // select active class
  const active = document.querySelector(".active");

  /* when a button is clicked, remove the active class 
from the button that has it */
  if (active) {
    active.classList.remove("active");
   }

  // Add active class to the clicked element
  et.classList.add("active");

  // select all classes with the name content
  let allContent = document.querySelectorAll('.content');

  // loop through all content classes
  for (let content of allContent) {

    /* display the content if the value in the data attribute of the button and content are the same */
    if(content.getAttribute('data-number') === button.getAttribute('data-number')) {
      content.style.display = "block";
     }

     // if it's not equal then hide it.
     else {
        content.style.display = "none";
      }
    }
 });
}
Enter fullscreen mode Exit fullscreen mode

Here is a demo in CodePen.

I hope my explanation was easy to understand and straight to the point. If there's anything that I missed, got wrong or I could've done better, please let me know.

Thank you.

Top comments (4)

Collapse
 
doublepicebs profile image
Doublepicebs • Edited

Good thing that you used loops! Usually, when the list of buttons is small, I define a function that resets everything, and set active styles on the pressed element.
Something like:

function activate(id)
    // All elements get the inactive here [...]
    document.querySelector(id).classList.add("active");
Enter fullscreen mode Exit fullscreen mode

A good hack for me is to put three text elements and hide all of them using css, and when a button gets pressed it will show it's own associated text element.
Your way is still way better than mine.

Collapse
 
mohdhussein profile image
Mohammed

Loops saved me here. My first solution was using ‘if else’ statement for each one. So the bigger the list the more I write.

I did what you said at first but I added more since its common for the first button to be clicked by default.

Thank you for your reply. 👍

Collapse
 
scrabble96 profile image
Scrabble96

I have found this very useful but I'd like to take it one stage further: as well as hiding the content relating to the other buttons when clicked, I'd like it to hide the content when clicking the open one again. So:

  1. Hide all content to begin with (like sub-menus in a menu).
  2. Click on a button to reveal its content
  3. Click on the same button to hide its own content again so all content is hidden (whilst maintaining the function you have above to close the content of another button when a different button is clicked)

I am going round in circles trying to achieve this with no success.

Collapse
 
mohdhussein profile image
Mohammed

Hey. I haven't figured a way to do number 3. If I came up with a solution I'll post it.