DEV Community

Cover image for An Easy Way to Make an Auto Responsive Menu
Bogdan Bendziukov
Bogdan Bendziukov

Posted on • Originally published at Medium on

An Easy Way to Make an Auto Responsive Menu

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.

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;
};
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

Now it looks fine:

Here’s the full demo of what we ahcieved:

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

Dynamic font-size using only CSS3


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


Read more posts on my Medium blog


Thanks for reading!

Stay safe and peace to you!

Top comments (0)