#javascript #html #jquery #dropdown
Добрый день! Подскажите, пожалуйста, реализацию, при которой бы при уменьшении экрана ссылки, которые не помещаются в одну строку, автоматически складывались бы в выпадающее меню. Благодарю за помощь! .header-item { padding: 7px 0; } .hi { display: inline-block; } .hi:after { content: '|'; margin: 0 17px 0; display: inline-block; color: #ccc; vertical-align: middle; } Уточняю вопрос: при уменьшении экрана необходимо, чтобы не все сразу ссылки помещались в выпадающее меню, а поочередно, по мере их выхода за пределы видимости экрана. спасибо!
Ответы
Ответ 1
Первым делом напишем необходимый 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
Ответ 2
#demo { margin: 30px 0 50px 0; font-family: Helvetica Neue, Helvetica, Arial, sans-serif; } #demo .wrapper { display: inline-block; width: 180px; margin: 0 10px 0 0; height: 20px; position: relative; } #demo .parent { height: 100%; width: 100%; display: block; cursor: pointer; line-height: 30px; height: 30px; border-radius: 5px; background: #F9F9F9; border: 1px solid #AAA; border-bottom: 1px solid #777; color: #282D31; font-weight: bold; z-index: 2; position: relative; -webkit-transition: border-radius .1s linear, background .1s linear, z-index 0s linear; -webkit-transition-delay: .8s; text-align: center; } #demo .parent:hover,с#demo .content:hover ~ .parent { background: #fff; -webkit-transition-delay: 0s, 0s, 0s; } #demo .content:hover ~ .parent { border-bottom-left-radius: 0; border-bottom-right-radius: 0; z-index: 0; } #demo .content { position: absolute; top: 0; display: block; z-index: 1; height: 0; width: 180px; padding-top: 30px; -webkit-transition: height .5s ease; -webkit-transition-delay: .4s; border: 1px solid #777; border-radius: 5px; box-shadow: 0 1px 2px rgba(0,0,0,.4); } #demo .wrapper:active .content { height: 123px; z-index: 3; -webkit-transition-delay: 0s; } #demo .content:hover { height: 123px; z-index: 3; -webkit-transition-delay: 0s; } #demo .content ul { background: #fff; margin: 0; padding: 0; overflow: hidden; height: 100%; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; } #demo .content ul a { text-decoration: none; } #demo .content li:hover { background: #eee; color: #333; } #demo .content li { list-style: none; text-align: left; color: #888; font-size: 14px; line-height: 30px; height: 30px; padding-left: 10px; border-top: 1px solid #ccc; } #demo .content li:last-of-type { border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }
Ответ 3
Автор ответа предлагает следующий скрипт: $().ready(function () { //Обновляем меню в событии window.resize $(window).on("resize", function (e) { var parentWidth = $("#nav-bar-filter").parent().width() - 40; var ulWidth = $("#more-nav").outerWidth(); var menuLi = $("#nav-bar-filter > li"); var liForMoving = new Array(); //Определим элементы, которые не влезают в меню menuLi.each(function () { ulWidth += $(this).outerWidth(); if (ulWidth > parentWidth) { liForMoving.push($(this)); } }); if (liForMoving.length > 0) { //Если есть элементы, которые не влезают -> перемещаем их в подменю e.preventDefault(); liForMoving.forEach(function (item) { item.clone().appendTo(".subfilter"); item.remove(); }); } else if (ulWidth < parentWidth) { //Проверяем, не нужно ли сдвинуть какие-то элементы обратно liForMoving = new Array(); var moved = $(".subfilter > li"); for (var i = moved.length - 1; i >= 0; i--) { var tmpLi = $(moved[i]).clone(); tmpLi.appendTo($("#nav-bar-filter")); ulWidth += $(moved[i]).outerWidth(); if (ulWidth < parentWidth) { $(moved[i]).remove(); } else { ulWidth -= $(moved[i]).outerWidth(); tmpLi.remove(); } } } if ($(".subfilter > li").length > 0) { //Если есть скрытые элементы, показываем блок еще $("#more-nav").show(); } else { $("#more-nav").hide(); } }); $(window).trigger("resize"); //Запустим скрипт при старте }); Демо: http://jsfiddle.net/3AU2N/16/ Перевод ответа https://stackoverflow.com/a/15499972/4500765
Комментариев нет:
Отправить комментарий