Responsive Menu Toggle with Alpine JS

Published August 2nd, 2020
4 minute read
Warning!
This was written over two years ago, so some information might be outdated. Frameworks and best practices change. The web moves fast! You may need to adjust a few things if you follow this article word for word.

Was updating my site today and noticed that my navbar is still using vanilla javascript to handle the toggling of the responsive menu at mobile size. This will not do!

Here's how I converted it to Alpine JS.

This was the script that was responsible for the behavior before:

1document.addEventListener('DOMContentLoaded', function () {
2 let toggleBtn = document.getElementsByClassName('menu-toggle')[0]
3 let menu = document.getElementsByClassName('navbar-menu')[0]
4 
5 toggleBtn.addEventListener('click', () => {
6 toggleBtn.classList.toggle('is-active')
7 menu.classList.toggle('hide')
8 })
9})
1document.addEventListener('DOMContentLoaded', function () {
2 let toggleBtn = document.getElementsByClassName('menu-toggle')[0]
3 let menu = document.getElementsByClassName('navbar-menu')[0]
4 
5 toggleBtn.addEventListener('click', () => {
6 toggleBtn.classList.toggle('is-active')
7 menu.classList.toggle('hide')
8 })
9})

Breaking that down, we're basically just attaching a "click" listener to the hamburger button (which has a class menu-toggle) which toggles some classes on the menu itself. Simple, but we had to write this big chunk of javascript to accomplish it. We can do better.

With Alpine we just need to add a few sprinkles to our template and we can get rid of all that javascript.

First, initialize a new component by setting some data on the parent tag. This will track the navbar's open/closed state.

1<div class="navbar" x-data="{ open: false }"></div>
1<div class="navbar" x-data="{ open: false }"></div>

Next, we need the button to change the open variable we just defined.

1<button class="menu-toggle" @click.prevent="open = !open">...</button>
1<button class="menu-toggle" @click.prevent="open = !open">...</button>

Finally, we just need the navbar to show and hide based on the state of our open data.

1<ul class="navbar-menu" :class="{ 'hide': !open }"></ul>
1<ul class="navbar-menu" :class="{ 'hide': !open }"></ul>

You could also use x-show to hide the element, I already had this "hide" class which has some CSS transitions attached to it, so I applied the class when open == false instead.

There you have it!

Don't know about you, but I'll take three properties in the DOM instead of that chunk of custom javascript any day.

Enjoy this article? Follow me on Twitter for more tips, articles and links.
😢 Awww, nobody has liked or mentioned this on Twitter yet.

Want Updates?

Sign up here if you want to stay in the loop about new articles or products I'm making.
I'll never spam you. Unsubscribe at any time.
Copyright ©2024 Austen Cameron