skip to Main Content

I have got follow html:

nav {
  width: 100px;
}


.nav-menu {
  background-color: orange;
}

.dropdown {
  position: relative;
}


a[data-toggle="dropdown"] {
  display: flex;
  align-items: center;
  background: transparent;
  color: blue;
  padding: 10px 15px;
  border-radius: 4px;
  transition: background 0.3s ease;
  white-space: nowrap;
}

a[data-toggle="dropdown"]:hover {
  color: black;
}

.nav-menu {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  list-style-type: none;
  padding: 0;
  margin: 0;
  align-items: center;
  width: 100%;

}

.dropdown-menu {
  list-style: none;
  padding: 10px 15px;
  margin: 0;
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 200px;
  background: #ffffff;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
  border-radius: 6px;
  overflow: hidden;
  transform: scaleY(0);
  transform-origin: top;
  opacity: 0;
  transition: transform 0.3s ease, opacity 0.3s ease;
  z-index: 1000;
}

.dropdown-menu.show {
  transform: scaleY(1);
  opacity: 1;
}

.dropdown-menu:before {
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  clip-path: inset(0 0 0 0);
}
<nav>
  <ul class="nav-menu">

    <li class="dropdown">
      <a href="#" data-toggle="dropdown">About</a>
      <ul class="dropdown-menu">
        <li><a href="/foo.html">Foo</a></li>
        <li><a href="/bar.html">Bar</a></li>
        <li><a href="/bar.html">Some long text here</a></li>
      </ul>
    </li>

  </ul>
</nav>

But I want to make menu be shown no wider than the dimensions of the container (orange color). The menu must always fit into the container.

menu tears apart the container

https://jsfiddle.net/Suliman123/8tg67sq4/

If menu is longer that container text menu it’s text should be fully displayed. In my case there is a lot of menu items. And if no space from right it always have space from left.

Here is illustration: https://jsfiddle.net/Suliman123/Lno7a5p0/
menu here should not be bigger than black region.

3

Answers


  1. you can delete this
    " min-width: 200px; "

    replace “width: 100%;”

    Edit :
    I edited it again, can you check it?

        let buttonIdCounter = 0;
      
    
        const dropdowns = document.querySelectorAll('.dropdown');
        dropdowns.forEach((dropdown) => {
          const button = dropdown.querySelector('a[data-toggle="dropdown"]');
          const menu = dropdown.querySelector('.dropdown-menu');
    
          const buttonId = `dropdown-button-${buttonIdCounter}`;
          const menuId = `dropdown-menu-${buttonIdCounter}`;
          buttonIdCounter++;
      
          button.dataset.buttonId = buttonId;
          menu.dataset.menuId = buttonId; 
         document.querySelector('nav').style.width=`${menu.offsetWidth}px`;
      
    
        });
        document.addEventListener('click', (event) => {
          const clickedButton = event.target.closest('a[data-toggle="dropdown"]');
          const openMenus = document.querySelectorAll('.dropdown-menu.show');
    
          openMenus.forEach(menu => {
            const menuId = menu.dataset.menuId;
            const relatedButton = document.querySelector(`a[data-button-id="${menuId}"]`);
            const arrow = relatedButton?.querySelector('.icon-arrow');
      
            if (arrow) {
              arrow.style.transform = "rotate(0)"; 
            }
      
            menu.classList.remove('show'); 
          });
    
          if (!clickedButton) return;
    
          const buttonId = clickedButton.dataset.buttonId;
          const relatedMenu = document.querySelector(`.dropdown-menu[data-menu-id="${buttonId}"]`);
          const arrow = clickedButton.querySelector('.icon-arrow');
      
          if (relatedMenu) {
            const isMenuOpen = relatedMenu.classList.toggle('show');
      
            if (arrow) {
              arrow.style.transform = isMenuOpen ? "rotate(180deg)" : "rotate(0)";
            }
          }
      
          event.preventDefault();
        });
        document.addEventListener('click', (event) => {
          if (!event.target.closest('.dropdown')) {
            const openMenus = document.querySelectorAll('.dropdown-menu.show');
            openMenus.forEach(menu => {
              const menuId = menu.dataset.menuId;
              const relatedButton = document.querySelector(`a[data-button-id="${menuId}"]`);
              const arrow = relatedButton?.querySelector('.icon-arrow');
      
              if (arrow) {
                arrow.style.transform = "rotate(0)"; 
              }
      
              menu.classList.remove('show'); 
            });
          }
        });
    
       
    nav {
       width:unset;
     }
       
    
    .nav-menu {
       background-color: orange;
     }
     
     .dropdown {
        position: relative;
        width:100%;
      }
       
      
      a[data-toggle="dropdown"] {
        display: flex;
        align-items: center;
        background: transparent;
        color: blue;
        padding: 10px 15px;
        border-radius: 4px;
        transition: background 0.3s ease;
        white-space: nowrap;
      }
      
      a[data-toggle="dropdown"]:hover {
        color: black;
      }
    
    .nav-menu {
        display: flex;
        flex-wrap: wrap; 
        gap: 10px;
        list-style-type: none;
        
        padding: 0;
        margin: 0;
        align-items: center;
        width: 100%;
        
    }
    
    
      .dropdown-menu {
        list-style: none;
        padding: 10px 15px;
        margin: 0;
        position: absolute;
        top: 100%;
        left: 0;
    
        background: #ffffff;
        box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
        border-radius: 6px;
        overflow: hidden;
        transform: scaleY(0);
        transform-origin: top;
        opacity: 0;
        transition: transform 0.3s ease, opacity 0.3s ease;
        z-index: 1000;
      }
      
      
        
      .dropdown-menu.show {
        transform: scaleY(1);
        opacity: 1;
      }
      
      .dropdown-menu:before {
        /* content: ""; */
        display: block;
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        clip-path: inset(0 0 0 0);
      }
    <div>
    
    
    <nav>
        <ul class="nav-menu">
    
            <li class="dropdown">
                <a href="#" data-toggle="dropdown">About</a>
                <ul class="dropdown-menu">
                  <li><a href="/foo.html">To long value To long value To long value </a></li>
                  <li><a href="/bar.html">Bar</a></li>
                </ul>
           </li>
    
        </ul>
    </nav>
    </div>
    Login or Signup to reply.
  2. We use offsetWidth property in JS to calculate the width of the button – then the event listener in js will apply this width to the dropdown using style.width property.

    You need to make these changes in CSS in the .dropdown-menu:

    width: auto;
    min-width: unset;
    

    This will remove any preset width or min-width in the CSS and will let the JS add on to your CSS.

    This will be your updated JS:

    document.querySelectorAll('.dropdown').forEach((dropdown) => {
      const button = dropdown.querySelector('a[data-toggle="dropdown"]');
      const menu = dropdown.querySelector('.dropdown-menu');
    
      button.addEventListener('click', (event) => {
        event.preventDefault();
        document.querySelectorAll('.dropdown-menu.show').forEach((openMenu) => {
          if (openMenu !== menu) {
            openMenu.classList.remove('show');
          }
        });
        const buttonWidth = button.offsetWidth;
        menu.style.width = `${buttonWidth}px`;
        menu.classList.toggle('show');
      });
    });
    
    // to close the dropdown when clicked anywhere else on the page
    document.addEventListener('click', (event) => {
      if (!event.target.closest('.dropdown')) {
        document.querySelectorAll('.dropdown-menu.show').forEach((menu) => {
          menu.classList.remove('show');
        });
      }
    });

    Your complete HTML, CSS and JS would become:

    document.querySelectorAll('.dropdown').forEach((dropdown) => {
      const button = dropdown.querySelector('a[data-toggle="dropdown"]');
      const menu = dropdown.querySelector('.dropdown-menu');
    
      button.addEventListener('click', (event) => {
        event.preventDefault();
    
        document.querySelectorAll('.dropdown-menu.show').forEach((openMenu) => {
          if (openMenu !== menu) {
            openMenu.classList.remove('show');
          }
        });
    
        const buttonWidth = button.offsetWidth;
        menu.style.width = `${buttonWidth}px`;
    
        // Toggle the visibility of the dropdown menu
        menu.classList.toggle('show');
      });
    });
    
    document.addEventListener('click', (event) => {
      if (!event.target.closest('.dropdown')) {
        document.querySelectorAll('.dropdown-menu.show').forEach((menu) => {
          menu.classList.remove('show');
        });
      }
    });
     nav {
       width: 100px;  
     }
       
    
    .nav-menu {
       background-color: orange;
     }
     
     .dropdown {
        position: relative;
      }
       
      
      a[data-toggle="dropdown"] {
        display: flex;
        align-items: center;
        background: transparent;
        color: blue;
        padding: 10px 15px;
        border-radius: 4px;
        transition: background 0.3s ease;
        white-space: nowrap;
      }
      
      a[data-toggle="dropdown"]:hover {
        color: black;
      }
    
    .nav-menu {
        display: flex;
        flex-wrap: wrap; 
        gap: 10px;
        list-style-type: none;
        padding: 0;
        margin: 0;
        align-items: center;
        width: 100%;
        
    }
    
    
      .dropdown-menu {
      list-style: none;
      padding: 10px 15px;
      margin: 0;
      position: absolute;
      top: 100%;
      left: 0;
      background: #ffffff;
      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
      border-radius: 6px;
      overflow: hidden;
      transform: scaleY(0);
      transform-origin: top;
      opacity: 0;
      transition: transform 0.3s ease, opacity 0.3s ease;
      z-index: 1000;
    
      /* just need to add this - this will remove any preset width or min-width */
      width: auto;
      min-width: unset;
    }
      
      
        
      .dropdown-menu.show {
        transform: scaleY(1);
        opacity: 1;
      }
      
      .dropdown-menu:before {
        /* content: ""; */
        display: block;
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        clip-path: inset(0 0 0 0);
      }
    <!-- UNCHANGED - NOTHING NEEDS TO BE CHANGED HERE IN HTML -->
    <nav>
        <ul class="nav-menu">
    
            <li class="dropdown">
                <a href="#" data-toggle="dropdown">About</a>
                <ul class="dropdown-menu">
                  <li><a href="/foo.html">Foo</a></li>
                  <li><a href="/bar.html">Bar</a></li>
                </ul>
           </li>
    
        </ul>
    </nav>
    Login or Signup to reply.
  3. Html code:

    <nav>
      <ul class="nav-menu">
        <li>
          <a href="#" data-toggle="dropdown">About</a>
          <ul class="dropdown">
            <li><a href="/foo.html">Hello World</a></li>
            <li><a href="/bar.html">Bar</a></li>
          </ul>
        </li>
        <li><a href="#">Services</a></li>
      </ul>
    </nav>
    

    CSS Code:

    * {
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }
    
    body {
      background: #efefef;
    }
    
    ul {
      list-style: none;
    }
    
    a {
      text-decoration: none;
    }
    
    nav {
      width: 300px;
    }
    
    .nav-menu {
      background-color: orange;
      display: flex;
      justify-content: center;
    }
    
    .nav-menu > li {
      position: relative;
    }
    
    .nav-menu > li > a {
      display: flex;
      align-items: center;
      background: transparent;
      color: blue;
      padding: 10px 15px;
      border-radius: 4px;
      transition: background 0.3s ease;
      white-space: nowrap;
    }
    
    .nav-menu > li > a:hover {
      color: black;
    }
    
    .dropdown {
      list-style: none;
      padding: 6px 8px;
      margin: 0;
      position: absolute;
      top: 100%;
      left: 0;
      width: 100%;
      background: #ffffff;
      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
      border-radius: 6px;
      overflow: hidden;
      transform: scaleY(0);
      transform-origin: top;
      opacity: 0;
      transition: transform 0.3s ease, opacity 0.3s ease;
      z-index: 1000;
    }
    
    .nav-menu li:hover .dropdown {
      transform: scaleY(1);
      opacity: 1;
    }
    
    .dropdown li > a {
      padding: 6px 8px;
      display: flex;
      transition: 0.5s;
      flex-direction: column;
      border-radius: 4px;
      white-space: nowrap;
    }
    .dropdown li > a:hover {
      background-color: #cccccc;
      transition: 0.5s;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search