Реализация большого выпадающего меню с несколькими уровнями вложенности
Коллеги, необходима ваша помощь - нужно реализовать большое выпадающее меню с 3 уровнями вложенности. Моих мозгов на данный момент не хватает чтобы продумать логику и последовательность.
По ссылке сверстанный мини пример - https://codepen.io/proququ/pen/eYNvmGq
Изначально меню выглядит следующим образом:

Т.е. по клику раскрывается шапка, верхнее меню перемещается в левую часть и перестраивается и мы видим три уровня меню, первый пункт выделен автоматически, соответственно первый подпункт тоже.
При клике на другие основные пункты меню, ранее выбранные скрываются и выезжают дочерние.
Я уже всю голову сломал, просто ховер здесь не подходит, знаний джса у меня не хватает, подумал что наверно более менее подходящяя идея, это по клику на бургер вырезать каждый уровень и поместить в одну из трех колонок, но не могу связать и анимировать клик и выезжание нужного подменю и... как вернуть меню снова вверх тоже не понимаю.
$('.burger').click(function(){
$(this).toggleClass(' active');
$(this).parents('.container').toggleClass(' drop-menu');
$('.menu').detach().prependTo('.big-nav__col--1');
$('.submenu').detach().prependTo('.big-nav__col--2');
$('.subsubmenu').detach().prependTo('.big-nav__col--3');
$('.bottom-row').slideToggle(350);
});
.container {
width: 80%;
padding: 10px 15px;
margin: 0 auto;
background-color: #ececec;
}
.upper-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
width: 30px;
height: 30px;
background-color: #1c1c1c;
}
.menu__list {
display: flex;
padding: 0;
margin: 0;
list-style: none;
}
.menu__list a {
display: block;
padding: 8px 14px;
text-decoration: none;
color: #444444;
transition: all 0.2s ease-in;
}
.submenu,
.subsubmenu{
display: none;
}
.bottom-row {
display: none;
padding: 20px 0;
}
.big-nav {
display: flex;
}
.big-nav__col {
width: 33.333%;
padding: 0 15px;
}
.big-nav .menu__list {
flex-direction: column;
}
.big-nav .menu__list a {
padding: 10px;
}
.big-nav .menu__list a:hover {
background-color: gray;
}
.big-nav .submenu,
.big-nav .subsubmenu {
display: block;
}
.info {
display: flex;
margin: 25px 0 15px;
}
.info p {
padding: 0;
margin: 0 30px 0 0;
font-size: 14px;
color: #444444;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="upper-row">
<div class="logo"></div>
<nav class="menu">
<ul class="menu__list">
<li>
<a href="#">Пункт 1</a>
<div class="submenu">
<ul class="submenu__list">
<li>
<a href="#">Подпункт 2 уровня</a>
<div class="subsubmenu">
<ul class="subsubmenu__list">
<li><a href="#">Подпункт 3 уровня</a></li>
<li><a href="#">Подпункт 3 уровня</a></li>
<li><a href="#">Подпункт 3 уровня</a></li>
<li><a href="#">Подпункт 3 уровня</a></li>
</ul>
</div>
</li>
<li><a href="#">Подпункт 2 уровня</a></li>
<li><a href="#">Подпункт 2 уровня</a></li>
<li><a href="#">Подпункт 2 уровня</a></li>
</ul>
</div>
</li>
<li>
<a href="#">Пункт 2</a>
</li>
<li>
<a href="#">Пункт 3</a>
<div class="submenu">
<ul class="submenu__list">
<li>
<a href="#">Подпункт 2 уровня</a>
<div class="subsubmenu">
<ul class="subsubmenu__list">
<li><a href="#">Подпункт 3 уровня</a></li>
<li><a href="#">Подпункт 3 уровня</a></li>
</ul>
</div>
</li>
<li><a href="#">Подпункт 2 уровня</a></li>
</ul>
</div>
</li>
<li>
<a href="#">Пункт 4</a>
</li>
</ul>
</nav>
<button class="burger">Меню</button>
</div>
<div class="bottom-row">
<div class="big-nav">
<div class="big-nav__col big-nav__col--1"></div>
<div class="big-nav__col big-nav__col--2">
при клике на основной пункт меню, в эту колонку слева выезжает подменю
</div>
<div class="big-nav__col big-nav__col--3">
при клике на пункт подменю, в эту колонку слева выезжает 3 уровень
</div>
</div>
<div class="info">
<p>Телефон компании</p>
<p>Адрес компании</p>
</div>
</div>
</div>
Заранее всем большое спасибо за помощь!)
Ответы (1 шт):
Идея в том, что все находящееся в выпадающем меню - это обычные табы, которые переключается между собой и внутри себя. Думаю, верхние элементы меню в навигации не должны никуда перестраиваться, они просто исчезают на момент раскрытия меню и появляются когда мы снова закрываем его. Стили использовать по своему усмотрению.
const nav = document.querySelector('.nav');
const burger = document.querySelector('.nav-burger');
const burgerHandler = () => {
nav.classList.toggle('active');
}
burger.addEventListener('click', burgerHandler);
const Tabs = (element, props) => {
const node = element;
let selectors = null;
let tabIndex = {
prev: 0,
next: 0
};
const requestSelectors = () => {
return selectors = {
tabsNavigationParent: node.querySelector('.tabs-navigation'),
tabsNavigationItems: [...node.querySelector('.tabs-navigation').children],
tabsContentParent: node.querySelector('.tabs-content'),
tabsContentItems: [...node.querySelector('.tabs-content').children]
}
}
const toggleContent = () => {
const { tabsNavigationItems, tabsContentItems } = selectors;
tabsContentItems[tabIndex.prev].classList.remove('active');
tabsNavigationItems[tabIndex.prev].classList.remove('active');
tabsContentItems[tabIndex.next].classList.add('active');
tabsNavigationItems[tabIndex.next].classList.add('active');
}
const requestActiveNodes = (index) => {
tabIndex.prev = tabIndex.next;
tabIndex.next = index;
if ( tabIndex.prev === tabIndex.next ) return;
toggleContent();
}
const init = () => {
const { tabsNavigationItems, tabsContentItems } = selectors;
tabsContentItems[tabIndex.next].classList.add('active');
tabsNavigationItems[tabIndex.next].classList.add('active');
tabsNavigationItems.forEach((label, i) => {
label.addEventListener('click', () => {
requestActiveNodes(i)
})
})
}
if(node) {
requestSelectors();
init();
}
}
const tabs = [...document.querySelectorAll('[data-widget="tabs"]')];
tabs.forEach(x => {
Tabs(x);
})
@import url("https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap");
* {
box-sizing: border-box;
}
body {
font-family: 'Roboto';
}
.nav {
border: 1px solid rgba(0, 0, 0, 0.1);
padding: 1rem 2rem;
display: grid;
gap: 2rem;
-webkit-box-align: center;
align-items: center;
grid-template-columns: auto 1fr auto;
background-color: white;
box-shadow: 4px 4px 50px -20px rgba(0, 0, 0, 0.1);
z-index: 3;
max-width: 1600px;
margin: 0 auto;
position: relative;
}
.nav-logo {
width: 2rem;
height: 2rem;
background-color: rgba(0, 0, 0, 0.5);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.nav-items {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
-webkit-transition: .3s;
transition: .3s;
}
.active .nav-items {
opacity: 0;
}
.nav-burger {
width: 2rem;
overflow: hidden;
cursor: pointer;
}
.nav-burger:before, .nav-burger:after {
display: block;
content: "";
background-color: rgba(0, 0, 0, 0.3);
height: 2px;
width: 100%;
margin: .5rem 0;
}
.nav-burger span {
display: block;
-webkit-transform: translatex(20%);
transform: translatex(20%);
width: 100%;
background-color: rgba(0, 0, 0, 0.3);
height: 2px;
-webkit-transition: .3s;
transition: .3s;
}
.active .nav-burger span {
-webkit-transform: translatex(0);
transform: translatex(0);
}
.nav-menu {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 80vh;
z-index: -1;
-webkit-transform: translatey(-100%);
transform: translatey(-100%);
-webkit-transition: .3s;
transition: .3s;
padding: 10rem 5rem;
display: grid;
grid-template-columns: auto 1fr;
gap: 2rem;
max-width: 1600px;
margin: 0 auto;
}
.nav-menu .item {
margin-bottom: 2rem;
}
.active .nav-menu {
-webkit-transform: translatey(0);
transform: translatey(0);
}
.tabs {
display: grid;
grid-template-columns: auto 1fr;
gap: 3rem;
}
.tabs-navigation > * {
padding: .5rem;
cursor: pointer;
}
.tabs-navigation > *.active {
color: #82c751;
}
.tabs-content > * {
display: none;
-webkit-animation: show .3s;
animation: show .3s;
}
.tabs-content > *.active {
display: block;
}
@-webkit-keyframes show {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes show {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<nav class="nav">
<div class="nav-logo"></div>
<div class="nav-items">
<div class="item">Оборудование</div>
<div class="item">Сервисные услуги</div>
<div class="item">Оснастка и аксессуары</div>
<div class="item">Полезные инструменты</div>
</div>
<div class="nav-burger"><span></span></div>
<div class="nav-menu">
<div class="container">
<div class="tabs" data-widget="tabs">
<div class="tabs-navigation">
<div class="item active">Оборудование</div>
<div class="item">Сервисные услуги</div>
</div>
<div class="tabs-content">
<div class="item">
<div data-widget="tabs" class="tabs">
<div class="tabs-navigation">
<div class="item">
#1 Оборудование
</div>
<div class="item">
#2 Оборудование
</div>
</div>
<div class="tabs-content">
<div class="item">
<p>#1-1 Оборудование</p>
<p>#1-2 Оборудование</p>
</div>
<div class="item">
<p>#2-1 Оборудование</p>
<p>#2-1 Оборудование</p>
</div>
</div>
</div>
</div>
<div class="item">
<div data-widget="tabs" class="tabs">
<div class="tabs-navigation">
<div class="item">
#1 Сервисные услуги
</div>
<div class="item">
#2 Сервисные услуги
</div>
</div>
<div class="tabs-content">
<div class="item">
<p>#1-1 Сервисные услуги</p>
<p>#1-2 Сервисные услуги</p>
</div>
<div class="item">
<p>#2-1 Сервисные услуги</p>
<p>#2-2 Сервисные услуги</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</nav>
