как в js и css выделить 2 элемента underline`ом

<nav class="menu">
      <ul class="menu__items">
        <li class="menu__item"><a class="menu__link" href="#1">текст</a></li>
        <li class="menu__item"><a class="menu__link" href="#2">тоже текст</a></li>
        <li class="menu__item"><a class="menu__link" href="#3">еще текст</a></li>
        <li class="menu__item"><a class="menu__link" href="#4">опять текст</a></li>
      </ul>
    </nav>

есть вот такое верхнее меню,которое отвечает за выбор вкладки ,нужно сделать так что бы активная кнопка выделялась с низу оранжевой полосой ,при этом если навестись курсором мыши на другую кнопку(не кликать,просто навести курсор),эта полоса растянулась бы от активного элемента до элемента на который был наведен курсор мыши. Идей как это сделать нет буду рад если кто поможет :)


Ответы (1 шт):

Автор решения: capchuck

Решение сыроватое, но как отправная точка вполне должно сойти. Основная идея в том, что у нас есть та самая полоска, которая ориентируется на координаты элементов, и расчитывает своё положение. Те элементы, что слева от - устанавливают left, те, что справа - width.

const getRelativePos = (parent, child) => {
    return {
    left: child.left - parent.left,
    top: child.top - parent.top,
    right: parent.right - child.right
  }
}

const menu = document.querySelector('.menu')
const items = document.querySelector('.menu__items')
const snake = document.querySelector('.menu__tab-snake')
const activeElement = document.querySelector('.menu__link--active')
const links = items.querySelectorAll('.menu__link')

const activeBR = activeElement.getBoundingClientRect()
const itemsBR = items.getBoundingClientRect()
let isHovering = false;

snake.style.left = activeBR.left + 'px'
snake.style.width = activeBR.right - activeBR.left + 'px'

links.forEach(link => link.addEventListener('mouseover', (e) => {
  if(e.target.classList.contains('menu__link--active')) return
      
  isHovering = true;
  
  const snakeBR = snake.getBoundingClientRect()
  const targetBR = e.target.getBoundingClientRect()
    
    // If target is left from active
    
  if (targetBR.left < snakeBR.left) {
    snake.style.left = getRelativePos(itemsBR, targetBR).left + 'px'
    snake.style.width = activeBR.right - targetBR.left + 'px'
  }
  // If target is right from active
  else {
    snake.style.width = targetBR.right - activeBR.left + 'px'
  }
}))

links.forEach(link => link.addEventListener('mouseleave', (e) => {
    isHovering = false
    setTimeout(() => {
    if (!isHovering) {
        snake.style.left = activeBR.left + 'px'
      snake.style.width = activeBR.right - activeBR.left + 'px'
    }
  }, 150)
}))
*, * * { /* scrollbar width? */
  box-sizing: border-box;
  margin: 0;
}

.menu__items {
  list-style: none;
  margin: 0;
  display: flex;
  position: relative;
}

.menu__item {
  margin-right: 10px;
}

.menu__item a {
  text-decoration: none;
}

.menu__tab-snake {
  position: absolute;
  bottom: 0;
  height: 2px;
  background: red;
  transition: all .3s;
  pointer-events: none;
}
<nav class="menu">
  <ul class="menu__items">
    <li class="menu__item"><a class="menu__link" href="#1">Линк 1</a></li>
    <li class="menu__item"><a class="menu__link" href="#2">Линк 2</a></li>
    <li class="menu__item"><a class="menu__link menu__link--active" href="#3">Активный линк</a></li>
    <li class="menu__item"><a class="menu__link" href="#4">Линк 4</a></li>
    <span class="menu__tab-snake"></span>
  </ul>
</nav>

→ Ссылка