Как создать меню с анимацией скольжения списка

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

.wrapper {
  position: relative;
}

.menu {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, min-content);
  column-gap: 30px;
  cursor: pointer;
}

.content {
  position: absolute;
  border: 1px solid grey;
}

.content-item {
  padding: 10px 12px;
  cursor: pointer;
}
<div class = "wrapper">
  
  <ul class = "menu">
    <li class = "menu-item">Item1</li>
    <li class = "menu-item">Item2</li>
    <li class = "menu-item">Item3</li>
  </ul>
  
  <div class = "content">
    <div class = "content-item">thing1</div>
    <div class = "content-item">thing1</div>
    <div class = "content-item">thing1</div>
  </div>
</div>

🤔 А знаете ли вы, что...
HTML (HyperText Markup Language) - это стандартный язык разметки для создания веб-страниц.


56
1

Ответ:

Решено

Я использовал JavaScript для этого типа меню, потому что его невозможно реализовать без JavaScript. Пожалуйста, проверьте мой пример ниже:

// script.js
document.addEventListener('DOMContentLoaded', () => {
    const menuItems = document.querySelectorAll('.menu li');
    const dropdown = document.getElementById('dropdown');
    
    const dropdownContent = {
        item1: ['Option A1', 'Option B1', 'Option C1'],
        item2: ['Option A2', 'Option B2', 'Option C2'],
        item3: ['Option A3', 'Option B3', 'Option C3']
    };

    menuItems.forEach(item => {
        item.addEventListener('mouseenter', (e) => {
            const dropdownList = dropdown.querySelector('ul');
            dropdownList.innerHTML = '';
            const data = dropdownContent[item.getAttribute('data-dropdown')];
            data.forEach(option => {
                const li = document.createElement('li');
                li.textContent = option;
                dropdownList.appendChild(li);
            });

            dropdown.style.display = 'block';
            const rect = item.getBoundingClientRect();
            dropdown.style.left = `${rect.left}px`;
        });

        item.addEventListener('mouseleave', () => {
            dropdown.style.display = 'none';
        });
    });

    dropdown.addEventListener('mouseenter', () => {
        dropdown.style.display = 'block';
    });

    dropdown.addEventListener('mouseleave', () => {
        dropdown.style.display = 'none';
    });
});
/* styles.css */
body {
    font-family: Arial, sans-serif;
}

.menu {
    display: flex;
    list-style: none;
    padding: 0;
    margin: 0;
}

.menu ul {
    display: flex;
    list-style: none;
    padding: 0;
    margin: 0;
}

.menu li {
    padding: 10px 20px;
    cursor: pointer;
    position: relative;
}

.dropdown {
    position: absolute;

    left: 0;
    display: none;
    width: 200px;
    background: #f9f9f9;
    border: 1px solid #ddd;
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
    transition: left 0.3s ease;
}

.dropdown ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

.dropdown ul li {
    padding: 10px;
    cursor: pointer;
}

.dropdown ul li:hover {
    background: #f1f1f1;
}
<!DOCTYPE html>
<html lang = "en">
<head>
    <meta charset = "UTF-8">
    <meta name = "viewport" content = "width=device-width, initial-scale=1.0">
</head>
<body>
    <div class = "wrapper">
  
    <nav class = "menu">
        <ul>
            <li data-dropdown = "item1" class = "menu-item">Item1</li>
            <li data-dropdown = "item2" class = "menu-item">Item2</li>
            <li data-dropdown = "item3" class = "menu-item">Item3</li>
        </ul>
    </nav>
    

    <div class = "dropdown" id = "dropdown">
        <ul class = "content">
            <li class = "content-item">Option A1</li>
            <li class = "content-item">Option B1</li>
            <li class = "content-item">Option C1</li>
        </ul>
    </div>
</div>
</body>
</html>