A vanilla JavaScript toggle for 2019

September 2019

It’s easy to create a toggler with modern vanilla JavaScript. However, most tutorials and StackOverflow answers haven’t caught up – they were written years ago in the days of jQuery, or their ways of doing things are extremely complex.

I’ll assume that your toggler needs to function like the following example. (Even if it doesn’t, you can likely adapt this tutorial to fit your needs.) Try it out:

Click me!
You look incredible today.

The HTML

The HTML is fairly simple. There are three things I should mention:

  • To have the toggler be open by default, remove its toggle-closed class.
  • You can add multiple HTML elements inside toggle-contents. Up to you.
  • The class names we’re using here matter because we’re also using them in our JavaScript and CSS. If you’d like to change them, make sure you do a full find and replace.
<div class="toggle toggle-closed">
  <div class="toggle-title">Click me!</div>
  <div class="toggle-contents">Contents go here.</div>
</div>

The JavaScript

When a .toggle-title is clicked, toggle the toggle-closed class on the parent. The CSS that follows this section will then hide or show the contents.

// Find every toggle title...
var toggleTitles = document.getElementsByClassName('toggle-title');

// Listen for clicks on each of them...
for (var i = 0; i < toggleTitles.length; i++) {
  toggleTitles[i].addEventListener("click", function(e) {

    // And when they're clicked, toggle a CSS class on their
    // parent to show or hide the content.
    var toggler = e.target.parentNode;
    if (toggler.classList.contains("toggle-closed")) {
      toggler.classList.remove("toggle-closed");
    } else {
      toggler.classList.add("toggle-closed");
    }
  });
}

The CSS

The only CSS you really need to make this work is a rule to hide .toggle-contents when it’s inside .toggle-closed:

/* Hide the contents if the toggler is closed. */
.toggle-closed .toggle-contents {
  display: none;
}

However, I’m guessing that you want to make it look a bit better. Remember my live demo from above? This is the CSS I used to make it. It adds a border, some hover effects, and a + and - sign to the right side of the toggle depending on if it’s open or closed.

/* Style the toggler's title. */
.toggle-title {
  color: #000;  
  cursor: pointer;
  font-weight: 500;
  padding: 1rem;
  transition: 100ms background ease-in-out, 100ms color ease-in-out;
}

.toggle-title:after {
  content: "-";
  float: right;
}

/* Control the title styling when the toggler is open/closed. */
.toggle-closed .toggle-title {
  color: #444;
}

.toggle-closed .toggle-title:after {
  content: "+";
}

/* Hide the contents if the toggler is closed. */
.toggle-closed .toggle-contents {
  display: none;
}

/* Control the title styling on hover. */
.toggle-title:hover {
  color: #000;
  background: #eee;
}

/* Add spacing between the title and the contents. */
.toggle-contents {
  padding: 1rem;
}

/* Style the toggler itself. */
.toggle {
  border-radius: 6px;
  border: 1px solid rgb(221, 221, 221);;
}

That’s all there is to it. If you enjoyed this tutorial, go make a t-shirt with my face on it.