. . .

Меню на js

13 Июнь 2019

Что можно отнести к простым элементам, которые можно встретить практически на любом сайте? В первую очередь приходит на ум меню сайта и сопутствующие элементы.

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

Предположим, что у нас есть блок меню со списком и кнопкой:

<header id="site-header">
  <button id="main-nav-btn" class="main-nav-btn">Меню</button>
  <ul class="main-nav-list">
    <li class="main-nav-list-item">Пункт 1</li>
    <li class="main-nav-list-item">Пункт 2</li>
    <li class="main-nav-list-item">Пункт 3</li>
  </ul>
</header>

Теперь добавим ему какое-то минимальное оформление:

header .main-nav-btn {
    display: none;
}  
header .main-nav-list li {
    list-style-type: none;
    display: inline;
    padding-right: 20px;
}

Добавим стили для мобильной версии сайта:

@media (max-width: 768px) {
    header .main-nav-btn {
        display: block;
    }
    header .main-nav-list {
        display: none;
        background-color: #ccc;
    }
    header .main-nav-list li {
        display: block;
        padding-right: 0;
        padding: 10px 0;
    }
}

На данном этапе меню выглядит следующим образом (первое - полная версия, второе - мобильная):

Теперь на очереди javascript. JS может добавлять стили самостоятельно, но я стараюсь по возможности избегать этого и придерживаться принципа html в html, css в css,  js в js. По-этому я воспользуюсь методом toggle.

//находим кнопку по ее id и добавляем функцию на событие клика
document.getElementById('main-nav-btn').onclick = function () {
  //находим весь блок header по id и добавляем ему класс site-header-opened
  document.getElementById('site-header').classList.toggle('site-header-opened');
}

Теперь добавим стили для элемента с классом site-header-opened:

.site-header-opened .main-nav-list {
    display: block;
}

Теперь в мобильной версии сайта меню будет выглядеть следующим образом:

Меню готово, однако это решение справедливо, если мы имеем дело с многостраничным сайтом, где при переходе по ссылке страница перезагружается и меню теряет класс site-header-opened. В одностраничном сайте, где пункты меню выполняют роль перехода по якорям страницы, страница прокрутится до нужного якоря, но меню останется открытым. Чтобы избежать этого мы можем добавить еще одну функцию, которая срабатывает при клике на пункт меню.

/*создаем переменную listItem которому присваиваем 
объект со всеми элементами с классом main-nav-list-item */
var listItems = document.getElementsByClassName('main-nav-list-item');
//циклом for перебираем все элементы объекта
for (var i=0; i<listItems.length; i++) {
  //каждому элементу добавялем функцию на событие клика
  listItems[i].onclick = function () {
    //убираем у site-header класс site-header-opened
    document.getElementById('site-header').classList.remove('site-header-opened');
  }
}

Теперь при клике на пункт меню страница прокрутится до заданного якоря, а меню при этом автоматически скроется.

Посмотреть на github