Logo

dev-resources.site

for different kinds of informations.

An Easy Way to Make an Auto Responsive Menu

Published at
10/3/2024
Categories
responsivewebdesign
javascript
css
html
Author
Bogdan Bendziukov
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;
};

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:

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!

Featured ones: