An Easy Way to Make an Auto Responsive Menu

Bogdan Bendziukov
3 min readMay 21, 2023

--

In this article I’m gonna show you a little hack about how to automatically collapse header’s menu into a “burger” and vice-versa.

Photo by Alex Pavlou on Unsplash

So the idea is simple — when the menu’s items cannot fit into the header they should be hidden and the mobile menu toggle button (the burger) will be shown. And it should be done automatically, without css media queries. So your menu still looks good on any device regardless of number of items, their font-sizes etc.

This is how it looks like:

I’ve made a very basic markup, with just a logo and a menu.
Then added some CSS to make it look nicer.

So in the “desktop” mode the header looks like this:

But when the viewport is too small to fit that menu, the menu items become “wrapped”:

We don’t need this! If there’s no space for them — then it’s time to hide the menu and show the menu toggle instead.

This is where a bit of JS gets handy. We need just to detect when the top position of any of the menu items will be different from the rest ones.

Here’s the trick:

/**
* Detect when elements become wrapped
*
* @param {NodeList} items - list of elements to check
* @returns {array} Array of items that were wrapped
*/
const detectWrap = (items) => {
let wrappedItems = [];
let prevItem = {};
let currItem = {};

for (let i = 0; i < items.length; i++) {
currItem = items[i].getBoundingClientRect();

if (prevItem) {
let prevItemTop = prevItem.top;
let currItemTop = currItem.top;

// if current's item top position is different from previous
// that means that the item is wrapped
if (prevItemTop < currItemTop) {
wrappedItems.push(items[i]);
}
}

prevItem = currItem;
}

return wrappedItems;
};

Then we can use that function to check if menu items were wrapped and if so — hide the menu and show a mobile toggle button.

const addWrapClasses = () => {
const menu = document.querySelector(".menu");
const menuItems = document.querySelectorAll(".menu > ul > li");

// remove ".wrapped" classes to detect which items was actually wrapped
menu.classList.remove("wrapped");

// only after that detect wrap items
let wrappedItems = detectWrap(menuItems); // get wrapped items

// if there are any elements that were wrapped - add a special class to menu
if (wrappedItems.length > 0) {
menu.classList.add("wrapped");
}
};

// execute function on page load
addWrapClasses();

// execute function on window resize
window.addEventListener("resize", addWrapClasses);

Now it looks fine:

Here’s the full demo of what we ahcieved:

Auto responsive menu demo

Check another trick for responsive font-size with only CSS:

If you find this article helpful — don’t hesitate to clap, subscribe and leave your thoughts in the comments 😊

Thanks for reading!
Stay safe and peace to you 💛💙!

--

--

Bogdan Bendziukov

I'm a web developer from Kyiv 💛💙. A WordPress enthusiast for 10 years. Writing tips and thoughts from my dev experience .