Recreating jQuery's basic "effects" in vanilla JS

I’m a big fan of small, reusable helper functions. My good friend and mentor, Chris Ferdinandi, maintains a fantastic collection over at The Vanilla JS Toolkit. Today, let’s create some for jQuery’s .hide(), .show(), and .toggle() methods using vanilla JS.

These jQuery methods control the visibility of an element using its inline display property. We could do that, but it’s much easier to just add a single class to our CSS:

.hidden {
  display: none;
}

Hide

You would use jQuery’s .hide() method to hide every item in the set of matching elements. To hide every element on the page with the .hide-me class, you would do this:

// Hide every element with the .hide-me class
$(".hide-me").hide();

Let’s create a function called hide(). It accepts one argument, element, which is the element we want to hide. All we need to do is add our .hidden class to the element.

To do that, we’ll call the DOMTokenList.add() method on the element’s classList property. The nice thing is that this method won’t throw an error if the element already has the class, or try to add it again.

/**
 * Hide an element
 * @param {Node} element The element to hide
 */
var hide = function (element) {
  element.classList.add("hidden");
};

We would use our hide() function by doing something like this:

// Get the first paragraph on the page...
var firstParagraph = document.querySelector("p");

// ...and hide it
hide(firstParagraph);

Show

You would use jQuery’s .show() method to display every item in the set of matching elements. For example, to show every element on the page with the class .show-me, you would do this:

// Show every element with the .show-me class
$(".show-me").show();

Let’s create our show() function. As before, it accepts one argument: element. This is the element we want to show. This time, we just need to remove our .hidden class from the element.

We’ll do that using the DOMTokenList.remove() method. This method won’t throw an error if the element doesn’t have the class we’re trying to remove.

/**
 * Show an element
 * @param {Node} element The element to show
 */
var show = function (element) {
  element.classList.remove("hidden");
};

To use our show() function, we would do something like the following:

// Get the first paragraph on the page...
var firstParagraph = document.querySelector("p");

// ...and show it
show(firstParagraph);

Toggle

In jQuery, the .toggle() method allows you to toggle an element’s visibility between hidden or shown. It does the same as the .hide() and .show() methods depending on the value of the element’s inline display property.

If an element with the class .some-class was hidden, the following snippet would show it; if it was visible, the snippet would hide it.

// Toggle every element with the class .some-class
$(".some-class").toggle();

For our toggle() function, we’ll again accept the single element argument. We’ll use the DOMTokenList.toggle() method to toggle our .hidden class.

/**
 * Toggle an element
 * @param {Node} element The element to toggle
 */
var toggle = function (element) {
  element.classList.toggle("hidden");
};

To toggle an element’s visibility, we would do something like this:

// Get the first paragraph on the page...
var firstParagraph = document.querySelector("p");

// ...and toggle it (show if hidden; hide if visible)
toggle(firstParagraph);

Looping

The thing about jQuery is that it has a feature called implicit iteration. As explained in the documentation for the .each() method:

Note: most jQuery methods that return a jQuery object also loop through the set of elements in the jQuery collection — a process known as implicit iteration. When this occurs, it is often unnecessary to explicitly iterate with the .each() method:

// The .each() method is unnecessary here:
$( "li" ).each(function() {
  $( this ).addClass( "foo" );
});

// Instead, you should rely on implicit iteration:
$( "li" ).addClass( "bar" );

Until now, we’ve only called our hide(), show(), and toggle() functions for single elements. What if we wanted to call them for several elements at once?

To do that, we can first use the .querySelectorAll() method to get the collection of elements as a NodeList.

We can then convert the NodeList to an array. This step isn’t strictly necessary, but it is if you want better browser support. The NodeList.forEach() method has no IE support, whereas the Array.forEach() method works in IE9 and above.

Note: you could also drop a polyfill for the NodeList.forEach() method into your project. You could even use polyfill.io to polyfill your site automatically. The polyfill for the NodeList.forEach() method isn’t included in their default bundle, though, so you’d need to explicitly tick the box when you visit their website (and the default bundle, if you want that as well).

Finally, we can loop through the array using the .forEach() method, calling the relevant function for each element.

// Get all elements with the class .some-class
var elements = document.querySelectorAll(".some-class");

// Convert the NodeList to an array
elements = Array.prototype.slice.call(elements);

// Hide the elements
elements.forEach(hide);

// Show the elements
elements.forEach(show);

// Toggle the elements
elements.forEach(toggle);

Wrapping up

And there you have it: the same basic functionality as jQuery’s basic “effects”, without the bloat of a 30 KB dependency. If you want to learn more about vanilla JS, I write articles about it here on my site, and my friend Chris Ferdinandi publishes awesome posts every weekday.


If you have questions, feedback, or any other suggestions, please do email me. I'd love to hear from you!