Как сверстать многоуровневое меню?

209
22 марта 2022, 12:30

Как сверстать такое многоуровневое меню?

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

Answer 1

Как-то чересчур сложно получилось.

var menuItems = document.querySelectorAll('.menu__item'); 
var currentItemName; 
var currentSubmenu; 
var currentSubmenuItems; 
var currentSubmenuInfoInner; 
 
menuItems.forEach(menuItem => { 
  menuItem.onmouseenter = () => { 
    currentItemName = menuItem.firstElementChild; 
    currentSubmenu = currentItemName.nextElementSibling; 
    currentSubmenuItems = currentSubmenu.querySelectorAll('.submenu__list__item'); 
    currentSubmenuInfoInner = currentSubmenu.querySelector('.submenu__info').firstElementChild; 
 
    var isAnySelected = [...currentSubmenuItems].find(csi => csi.classList.contains('submenu__list__item_selected')); 
    if (!isAnySelected) { 
      currentSubmenuItems[0].classList.add('submenu__list__item_selected'); 
      currentSubmenuInfoInner.style.backgroundColor = currentSubmenuItems[0].dataset.color; 
    } 
 
    currentSubmenuItems.forEach(currentSubmenuItem => { 
      currentSubmenuItem.onmouseenter = () => { 
        currentSubmenuItems.forEach(csi => csi.classList.remove('submenu__list__item_selected')); 
 
        currentSubmenuItem.classList.add('submenu__list__item_selected'); 
        currentSubmenuInfoInner.style.backgroundColor = currentSubmenuItem.dataset.color; 
      }; 
    }); 
 
    currentItemName.classList.add('menu__item__name_selected'); 
    currentSubmenu.classList.add('submenu_shown'); 
 
    currentSubmenuBox = currentSubmenu.getBoundingClientRect(); 
    if (currentSubmenuBox.right > innerWidth) { 
      currentSubmenu.style.left = `${innerWidth - currentSubmenuBox.left}px`; 
    } 
  }; 
 
  menuItem.onmouseleave = () => { 
    currentItemName.classList.remove('menu__item__name_selected'); 
    currentSubmenu.classList.remove('submenu_shown'); 
  }; 
});
:root { 
  --menu-height: 20vh; 
  --submenu-height: 80vh; 
} 
 
* { 
  margin: 0; 
  padding: 0; 
  box-sizing: border-box; 
} 
 
body { 
  overflow: hidden; 
} 
 
ul { 
  list-style: none; 
} 
 
.menu { 
  position: relative; 
  height: var(--menu-height); 
  display: flex; 
  background-color: #633e8e; 
  color: white; 
} 
 
.menu__item { 
  flex-grow: 1; 
  box-shadow: -0.4px 0 0 white; 
} 
 
.menu__item__name { 
  width: 100%; 
  height: 100%; 
  padding: 0 1rem; 
  display: flex; 
  align-items: center; 
  justify-content: center; 
} 
 
.menu__item__name_selected { 
  background-color: #4b2975; 
} 
 
.submenu { 
  position: absolute; 
  bottom: 100%; 
  left: 0; 
  height: var(--submenu-height); 
  width: 100%; 
  padding: 1rem; 
  display: flex; 
  background-color: #4b2975; 
  transition: transform 1s; 
  z-index: -1; 
} 
 
.submenu_shown { 
  transform: translateY(calc(100% + var(--menu-height))); 
} 
 
.submenu__list { 
  flex-grow: 1; 
  display: flex; 
  flex-direction: column; 
} 
 
.submenu__list__item { 
  flex-grow: 1; 
  padding-left: 1rem; 
  display: flex; 
  align-items: center; 
  border-radius: 5px; 
  border-top-right-radius: 0; 
  border-bottom-right-radius: 0; 
} 
 
.submenu__list__item_selected { 
  background-color: #906abd; 
} 
 
.submenu__info { 
  flex-grow: 3; 
  padding: 1rem; 
  background-color: #906abd; 
  border-radius: 5px; 
  border-top-left-radius: 0; 
  border-bottom-left-radius: 0; 
} 
 
.submenu__info__inner { 
  width: 100%; 
  height: 100%; 
}
<ul class="menu"> 
  <li class="menu__item"> 
    <div class="menu__item__name">Суши</div> 
 
    <div class="submenu"> 
      <ul class="submenu__list"> 
        <li class="submenu__list__item" data-color="tomato">Запеченные острые суши</li> 
        <li class="submenu__list__item" data-color="coral">Запеченные суши</li> 
        <li class="submenu__list__item" data-color="lightblue">Классические суши</li> 
        <li class="submenu__list__item" data-color="lightgreen">Острые суши</li> 
      </ul> 
 
      <div class="submenu__info"> 
        <div class="submenu__info__inner"></div> 
      </div> 
    </div> 
  </li> 
 
  <li class="menu__item"> 
    <div class="menu__item__name">Суши</div> 
 
    <div class="submenu"> 
      <ul class="submenu__list"> 
        <li class="submenu__list__item" data-color="tomato">Запеченные острые суши</li> 
        <li class="submenu__list__item" data-color="coral">Запеченные суши</li> 
        <li class="submenu__list__item" data-color="lightblue">Классические суши</li> 
        <li class="submenu__list__item" data-color="lightgreen">Острые суши</li> 
      </ul> 
 
      <div class="submenu__info"> 
        <div class="submenu__info__inner"></div> 
      </div> 
    </div> 
  </li> 
 
  <li class="menu__item"> 
    <div class="menu__item__name">Суши</div> 
 
    <div class="submenu"> 
      <ul class="submenu__list"> 
        <li class="submenu__list__item" data-color="tomato">Запеченные острые суши</li> 
        <li class="submenu__list__item" data-color="coral">Запеченные суши</li> 
        <li class="submenu__list__item" data-color="lightblue">Классические суши</li> 
        <li class="submenu__list__item" data-color="lightgreen">Острые суши</li> 
      </ul> 
 
      <div class="submenu__info"> 
        <div class="submenu__info__inner"></div> 
      </div> 
    </div> 
  </li> 
 
  <li class="menu__item"> 
    <div class="menu__item__name">Суши</div> 
 
    <div class="submenu"> 
      <ul class="submenu__list"> 
        <li class="submenu__list__item" data-color="tomato">Запеченные острые суши</li> 
        <li class="submenu__list__item" data-color="coral">Запеченные суши</li> 
        <li class="submenu__list__item" data-color="lightblue">Классические суши</li> 
        <li class="submenu__list__item" data-color="lightgreen">Острые суши</li> 
      </ul> 
 
      <div class="submenu__info"> 
        <div class="submenu__info__inner"></div> 
      </div> 
    </div> 
  </li> 
 
</ul>

Answer 2

На CSS

body { 
  margin: 0; 
} 
 
.nav { 
  display: flex; 
  flex-direction: row; 
  height: 50px; 
  background: #633e8e; 
  color: #fff; 
  padding: 0 10px; 
  box-sizing: border-box; 
  position: relative; 
} 
 
.nav a { 
  color: inherit; 
} 
 
.nav>.item { 
  display: flex; 
  justify-content: center; 
  align-items: center; 
  height: 100%; 
  cursor: pointer; 
  padding: 0 10px; 
  box-sizing: border-box; 
} 
 
.nav>.item.drop::after { 
  content: ''; 
  display: inline-block; 
  width: 0; 
  height: 0; 
  border: 4px solid transparent; 
  margin-left: 5px; 
  border-top: 6px solid #a892c1; 
  transform: translateY(4px); 
} 
 
.nav>.item:not(:last-child) { 
  border-right: 1px solid #7d5ba7; 
} 
 
.nav>.item:hover { 
  background: #4b2975; 
} 
 
.nav>.item>.droped { 
  display: none; 
  width: 100%; 
  min-height: 200px; 
  padding: 10px; 
  background: #4b2975; 
  box-sizing: border-box; 
  position: absolute; 
  top: 50px; 
  left: 0; 
  right: 0; 
} 
 
.nav>.item:hover .droped { 
  display: block; 
} 
 
.nav>.item .droped>.item { 
  display: flex; 
  flex-direction: row; 
  width: 50%; 
  padding: 5px 10px; 
  border-radius: 4px; 
  box-sizing: border-box; 
  cursor: pointer; 
} 
 
.nav>.item .droped>.item.drop { 
  border-radius: 4px 0 0 4px; 
} 
 
.nav>.item .droped>.item:hover { 
  background: #906abd; 
} 
 
.nav>.item .droped>.item>.droped { 
  display: none; 
  flex-direction: column; 
  justify-content: flex-start; 
  align-items: center; 
  width: calc(50% - 10px); 
  min-height: calc(100% - 20px); 
  background: #906abd; 
  padding: 10px; 
  border-radius: 4px; 
  overflow: hidden auto; 
  box-sizing: border-box; 
  position: absolute; 
  top: 10px; 
  right: 10px; 
  bottom: 10px; 
} 
 
.nav>.item .droped>.item>.droped img { 
  display: block; 
  max-width: 200px; 
  max-height: 150px; 
  object-fit: contain; 
} 
 
.nav>.item .droped>.item:hover .droped { 
  display: flex; 
} 
 
.nav>.item .droped>.item:first-child>.droped { 
  border-top-left-radius: 0; 
}
<div class="nav"> 
  <div class="item drop"> 
    <div class="text">Суши</div> 
    <div class="droped"> 
      <div class="item drop"> 
        <div class="text">Запеченные острые суши</div> 
        <div class="droped"> 
          <img src="https://i.imgur.com/GkVXrea.png"><br> 
          <a href="#">Суши с доставкой - полезное, вкусное и практичное решение вопроса питая в</a> 
        </div> 
      </div> 
      <div class="item drop"> 
        <div class="text">Запеченные суши</div> 
        <div class="droped"></div> 
      </div> 
      <div class="item drop"> 
        <div class="text">Классические суши</div> 
        <div class="droped"></div> 
      </div> 
      <div class="item drop"> 
        <div class="text">Острые суши</div> 
        <div class="droped"></div> 
      </div> 
    </div> 
  </div> 
  <div class="item drop"> 
    <div class="text">Роллы</div> 
    <div class="droped"> 
      <div class="item drop"> 
        <div class="text">Запеченные острые суши</div> 
        <div class="droped"> 
          <img src="https://i.imgur.com/GkVXrea.png"><br> 
          <a href="#">Суши с доставкой - полезное, вкусное и практичное решение вопроса питая в</a> 
        </div> 
      </div> 
      <div class="item drop"> 
        <div class="text">Запеченные суши</div> 
        <div class="droped"></div> 
      </div> 
      <div class="item drop"> 
        <div class="text">Классические суши</div> 
        <div class="droped"></div> 
      </div> 
      <div class="item drop"> 
        <div class="text">Острые суши</div> 
        <div class="droped"></div> 
      </div> 
    </div> 
  </div> 
  <div class="item drop"> 
    <div class="text">Наборы</div> 
    <div class="droped"> 
      <div class="item drop"> 
        <div class="text">Запеченные острые суши</div> 
        <div class="droped"> 
          <img src="https://i.imgur.com/GkVXrea.png"><br> 
          <a href="#">Суши с доставкой - полезное, вкусное и практичное решение вопроса питая в</a> 
        </div> 
      </div> 
      <div class="item drop"> 
        <div class="text">Запеченные суши</div> 
        <div class="droped"></div> 
      </div> 
      <div class="item drop"> 
        <div class="text">Классические суши</div> 
        <div class="droped"></div> 
      </div> 
      <div class="item drop"> 
        <div class="text">Острые суши</div> 
        <div class="droped"></div> 
      </div> 
    </div> 
  </div> 
</div>

READ ALSO
Получить текущий url iframe?

Получить текущий url iframe?

Возможно ли и как получить текущий url iframe ( отличный от начального src ) ?

64
Access Violation при работе с CSP

Access Violation при работе с CSP

Есть библиотека для работы с криптопровайдером наNET Core

88
Передать типы данных из C# в DLL на С

Передать типы данных из C# в DLL на С

Я создал веб-проект на ASPNET CORE и к нему собрал и подключил библиотеку, написанную на C

84