0

I want to use Floating UI to prevent dropdown menus from going off the left/right edge of the screen. The example code is as follows:

HTML:

<ul class="menu">
  <li class="menu__item">
    <a href="#" class="menu__link">Item 1</a>
    <ul class="submenu">
      <li><a href="">Item 1.1</a></li>
      <li><a href="">Item 1.2</a></li>
      <li><a href="">Item 1.3</a></li>
      <li><a href="">Item 1.4</a></li>
      <li><a href="">Item 1.5</a></li>
    </ul>
  </li>
  <li class="menu__item">
    <a href="#" class="menu__link">Item 2</a>
    <ul class="submenu">
      <li><a href="">Item 2.1</a></li>
      <li><a href="">Item 2.2</a></li>
      <li><a href="">Item 2.3</a></li>
      <li><a href="">Item 2.4</a></li>
      <li><a href="">Item 2.5</a></li>
    </ul>
  </li>
  <li class="menu__item">
    <a href="#" class="menu__link">Item 3</a>
    <ul class="submenu">
      <li><a href="">Item 3.1</a></li>
      <li><a href="">Item 3.2</a></li>
      <li><a href="">Item 3.3</a></li>
      <li><a href="">Item 3.4</a></li>
      <li><a href="">Item 3.5</a></li>
    </ul>
  </li>
  <li class="menu__item">
    <a href="#" class="menu__link">Item 4</a>
    <ul class="submenu">
      <li><a href="">Item 4.1</a></li>
      <li><a href="">Item 4.2</a></li>
      <li><a href="">Item 4.3</a></li>
      <li><a href="">Item 4.4</a></li>
      <li><a href="">Item 4.5</a></li>
    </ul>
  </li>
  <li class="menu__item">
    <a href="#" class="menu__link">Item 5</a>
    <ul class="submenu">
      <li><a href="">Item 5.1</a></li>
      <li><a href="">Item 5.2</a></li>
      <li><a href="">Item 5.3</a></li>
      <li><a href="">Item 5.4</a></li>
      <li><a href="">Item 5.5</a></li>
    </ul>
  </li>
</ul>

CSS:

* {
  margin: 0;
  padding: 0;
}
ul {
  list-style-type: none;
  display: flex;
}
a {
  color: inherit;
  text-decoration: none;
}
.menu {
  display: flex;
  gap: 5px;
  justify-content: space-around;
  color: white;
}
.menu > li {
  position: relative;
  background: blue;
  padding: 0 30px;
  height: 40px;
}
.submenu {
  display: none;
  position: absolute;
  left: 50%;
  top: 40px;
  transform: translateX(-50%);
  background: red;
}
.menu > li:hover .submenu {
  display: flex;
}
.submenu li {
  padding: 10px 20px;
}
.submenu a {
  white-space: nowrap;
}

JS:

import { autoUpdate, computePosition, shift } from "https://cdn.skypack.dev/@floating-ui/dom@1.2.0";

const menuItems = document.querySelectorAll('.menu__item');
menuItems.forEach((item) => {
  const reference = item.querySelector('.menu__link');
  const floating = item.querySelector('.submenu');
  
  computePosition(reference, floating, {
    placement: "bottom",
    middleware: [shift()]
  }).then(({ x, y }) => {
    Object.assign(floating.style, {
      left: `${x}px`
    });
  });
});

There's a CodePen here.

However, I'm struggling to understand the documentation and the implementation I have doesn't seem to work. The red dropdowns should be center-aligned under the blue items where possible but Floating UI should adjust the positioning horizontally so that the first dropdown should have its left edge aligned to the left of the screen and the last dropdown should have its right edge aligned to the right of the screen.

Could anyone advise how to get this working and ensure that it maintains the correct positioning even after window resizing?

Many thanks.

Dan
  • 5,836
  • 22
  • 86
  • 140

0 Answers0