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

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

mohdhussein profile image Mohammed ・2 min read

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>

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>

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

.content:not(:first-child) {
    display: none;
}

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";
      }
    }
 });
}

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.

Discussion

markdown guide
 

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");

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.

 

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. 👍