Страницы

Поиск по вопросам

понедельник, 8 апреля 2019 г.

Как реализовать автоматическое выпадающее меню?

Добрый день! Подскажите, пожалуйста, реализацию, при которой бы при уменьшении экрана ссылки, которые не помещаются в одну строку, автоматически складывались бы в выпадающее меню. Благодарю за помощь!
.header-item { padding: 7px 0; } .hi { display: inline-block; } .hi:after { content: '|'; margin: 0 17px 0; display: inline-block; color: #ccc; vertical-align: middle; }


Уточняю вопрос: при уменьшении экрана необходимо, чтобы не все сразу ссылки помещались в выпадающее меню, а поочередно, по мере их выхода за пределы видимости экрана. спасибо!


Ответ

Первым делом напишем необходимый CSS: добавим всем элементам white-space: nowrap, чтобы они не переносились на следующую строку; скроем меню по правилам доступности — это нам также потребуется в дальнейшем при расчетах ширины скрытых элементов. При нажатии на кнопку будем отображать и скрывать меню с элементами, которые не поместились в список. Функция getInvisible() возвращает нам массив элементов, которые не помещаются в ширину списка. Основа всех расчетов — метод .getBoundingClientRect() Функция moveForward() переносит все не помещающиеся элементы в выпадающее меню. Функция moveBackward() переносит элементы из выпадающего меню обратно — это нам потребуется при ресайзе окна. Функция debounce() нужна для оптимизации вызова функции при ресайзе. Добавляем слушателя на событие ресайза и вызываем функцию restart(), которая вызывает moveBackward() и moveForward(). Таким образом, при ресайзе все элементы возвращаются обратно в строку, а затем те, которые не помещаются отправляются обратно в выпадающий список.
UPD. добавил также подсчет количества скрытых элементов и скрытие кнопки, когда все элементы меню видны.
let button = document.getElementById('menu-toggler'); button.addEventListener('click', function() { document.querySelector('.menu').classList.toggle('menu--open'); }); window.addEventListener('resize', debounce(restart, 250)); moveForward(); function moveForward() { let listElements = Array.from(document.querySelectorAll('#list .li')), invisibleElements = getInvisible(listElements), menuList = document.getElementById('menu-list'); invisibleElements.forEach(function(item) { menuList.appendChild(item); }); if(!invisibleElements.length) { button.setAttribute('hidden', true); } else { button.removeAttribute('hidden'); } button.innerHTML = invisibleElements.length; } function moveBackward() { let menuListElements = Array.from(document.querySelectorAll('#menu-list .li')), list = document.getElementById('list'); menuListElements.forEach(function(item) { list.appendChild(item); }); } function restart() { moveBackward(); moveForward(); } function getInvisible(listElements) { let list = document.getElementById('list'); let invisible = listElements.filter(function(item) { if (item.getBoundingClientRect().left + item.getBoundingClientRect().width > list.clientWidth) { return item; } }); return invisible; } function debounce(func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; #menu-toggler { position: absolute; right: 8px; top: 8px; width: 35px; height: 35px; } #list { width: calc(100% - 100px); padding: 0; margin: 0; white-space: nowrap; border: 1px solid #000; font-size: 0; overflow: hidden; } #menu-list { margin: 0; padding: 0; } .li { display: inline-block; padding: 5px 10px; font-size: 16px; } .menu { border: 1px solid; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; right: 8px; top: 50px; } .menu--open { clip: auto; height: auto; margin: 0; overflow: visible; width: 150px; }

  • element #1
  • element #2
  • element #3
  • element #4
  • element #5
  • element #6
  • element #7
  • element #8
  • element #9
  • element #10
  • element #11
  • element #12
  • element #13
  • element #14
  • element #15
  • element #16
  • element #17
  • element #18
  • element #19
  • element #20

Комментариев нет:

Отправить комментарий