Дебаунсинг выпадающего списка (меню сайта) средствами одного CSS / Habr
Предыстория
Около пяти-шести лет назад я переделывал меню на рабочем сайте (не называю). Меняли меню каталога со старомодного разворачивающегося на (сейчас относительно) современное выпадающее. Меню делали горизонтальное, выпадающее вправо.
Коллега обратил мое внимание на проблему «цепляния за соседние пункты» при передвижении курсора мыши к выпавшим подпунктам меню. Он предложил решить ее так, как это было тогда сделано на сайте Амазона, и скинул мне местную статью Загадка выпадающего списка «Амазона» (где и постановка задачи и описание решения и ссылки на).
Но мне не хотелось не глядя вставлять чужое решение, не хотелось разбираться в нем, не хотелось писать свой велосипед, зато как-то быстро пришла в голову идея своего на одном лишь CSS. И получилось удобоваримо.
Я долго ждал, когда увижу, что кто-то сделал что-то подобное (и мне не придется писать на Хабр), но пока не дождался. Возможно плохо смотрел.
Проблема
Для выпадающих меню (особенно выпадающих горизонтально) при управлении мышкой существует неприятный момент при перемещении курсора от выбранного пункта к развернутому блоку подпунктов: часто приходится двигать курсор не по прямой, а по кривой, так чтобы не задеть соседние корневые пункты.
На картинке, думаю, понятно изображено. Двигать нужно по синим стрелкам. Кратчайшее движение по красной стрелке приведет к перескоку на пункты 4 и 3. Кто хочет проверить: ссылка на jsfiddle.
Мое решение
Живой пример возможно многим пояснит лучше дальнейших слов.
Мое решение: при зависании мыши над корневым пунктом меню закрываем соседние пункты прозрачным дочерним элементом (dom-елементом) этого пункта, таким образом, чтобы на соседних элементах событие hover уже не происходило.
В примере для наглядности этот вспомогательный элемент div. unhover сделал полупрозрачным красным. В продакте, конечно, ставим ему в стиле background: transparent.
А чтобы другой корневой пункт все-таки можно было выбрать, прячем этот вспомогательный div, если курсор передвинут непосредственно на него или на выпавший блок. Но делаем это с анимацией свойства width этого вспомогательного элемента.
В общем при движении курсора к подпунктам (зеленая стрелка) эта «шторка» div.unhover плавно но быстро сворачивается ему вслед. Скорость анимации нужно подбирать по ширине меню и скорости движения мыши среднестатистического посетителя.
Чтобы не происходило осцилляций вспомогательного блока, названия корневых пунктов обернуты в span‘ы, которые при наведении получают больший z-index, чем их сестринский div.unhover.
Заключение
Оригинальное амазоновское решение по юзабилити лучше, так как не зависит от скорости движения мыши и имеет минимальную задержку при движении мыши между корневыми пунктами.
Но в последнее время даже на ведущих сайтах в лучшем случае отделываются простой задержкой переключения корневых пунктов. Оно и понятно тач-интерфейсы основательно вышли на передний план.
Выпадающее меню с использованием только CSS и недокументированных возможностей элемента флажка
В этом уроке мы рассмотрим создание выпадающего меню на чистом CSS. Этот способ основан на применении элемента HTML флажка и интересном использовании классов и селекторов CSS без единой строки JavaScript. Демонстрацию работы этого способа и весь нужный код можно увидеть ниже. Также можно скачать полный исходный код по ссылке в конце урока.
Разметка
Структура HTML выглядит следующим образом. Важно отметить, что элемент ввода должен располагаться первым, до элементов подписи и ненумерованного списка. Позже, когда мы будем разбирать код CSS, станет понятно, почему.
<div> <input type="checkbox"> <label for="checkbox_toggle">Click to Expand</label> <ul> <li><a href="#">Link One</a></li> <li><a href="#">Link Two</a></li> <li><a href="#">Link Three</a></li> <li><a href="#">Link Four</a></li> </ul> </div>
Как Вы видите, здесь нет ничего сложного, все элементы HTML обычные, широко используемые:
- В блочном элементе находится все остальное.
- Элемент ввода типа флажок нужен из-за его возможности быть установленным или неустановленным. Он будет спрятан все время.
- Элемент подписи будет использоваться для переключения состояния элемента ввода и вызова выпадающего меню.
- Элемент ненумерованного списка — это просто список, который нужно сделать видимым, когда развернуто выпадающее меню. Это может быть и любой другой элемент.
Недокументированные возможности элемента флажка
Нам нужен элемент флажка только ради его установленного состояния, которому можно задать стили с помощью псевдокласса :checked. Установка и снятие флажка делается посредством нажатия на элемент подписи, что является обычной функцией браузера. Сначала спрячем элемент флажка:
input[type=checkbox]{ display: none; }
Еще спрячем по умолчанию элемент ненумерованного списка — это выпадающее меню, которое должно быть видно, только когда оно развернуто:
ul{ display: none; }
А вот и недокументированная возможность. Если объединить псевдокласс :checked с родственным селектором ~, можно изменять свойства CSS элементов, следующих за элементом флажка. Это причина, по которой нужно, чтобы элемент флажка располагался выше других элементов в дереве объектов документа.
input[type=checkbox]:checked ~ ul { display: block }
Код выше покажет ненумерованный список, только если установлен флажок. Так как у элемента ввода типа флажок возможно только два состояния, он отлично подходит для переключения элементов между развернутым и спрятанным состояниями.
Надеемся, вам понравился этот урок.
Автор урока Danny Markov
Перевод — Дежурка
Смотрите также:
- Меню для сайта рок-группы: хаотичное расположение с использованием трансформаций CSS
- Простое анимированное горизонтальное меню с использованием HTML5 и CSS
- Создание меню в ромбовидной сетке с использованием CSS
- Опубликовано в css, ноября 3, 2016
- Метки: css, css3, верстка, урок css, урок css3, урок верстка
Tweet
�
Комментарии
[an error occurred while processing the directive]
раскрывающихся список • Pico.
css выпадают с < Подробная информация Роль = "Список" >
в качестве обертки и < Сводная сумма >
и < UL >
Для согласованности стиля с элементами формы выпадающие списки по умолчанию имеют стиль
Раскрывающийся список- Действие
- Другое действие
- Что-то еще здесь
< детали роль = "список" > < резюме aria-haspopup = "список" >Dropdown резюме > < ul роль = "список" > < li >< a >Действие a > li > < li >< a >Другое действие a > ли > < li >< a >Что-то еще здесь a > li > ул > подробности > < выберите > < опция значение = "" отключено выбрано >Выбрать опция > < опция >… опция > выберите >
< резюме роль = "кнопка" >
превращает раскрывающийся список в кнопку.
- Action
- Another action
- Something else here
- Action
- Another action
- Something else here
- Action
- Another action
- Что-то еще здесь
< детали роль = "список" > < резюме aria-haspopup = "список" роль = "кнопка" > Выпадающий список как кнопка 1 резюме > < ul роль = "список" > < li >< a >Действие a > li > < li >< a >Другое действие a > ли > < li >< a >Что-то еще здесь a > li > ул > подробности > < детали роль = "список" > < сводка aria-haspopup = "список" роль = "кнопка" класс = "вторичный" > Выпадающий список как кнопка 2 резюме > < ul роль = "список" > < li >< a >Действие a > li > < li >< a >Другое действие a > li > < li >< a >Что-то еще здесь a > li > ул > подробности > < детали роль = "список" > < сводка aria-haspopup = "список" роль= "кнопка" класс = "контраст" > Выпадающий список как кнопка 3 резюме > < ul роль = "список" > < li >< a >Действие a > li > < ли >< a >Другое действие a > li > < li >< a >Что-то еще здесь a > li > ул > подробности >
Выпадающие списки могут использоваться как пользовательские выборки с вводом Выпадающие списки могут использоваться внутри Пример с выпадающим списком в качестве ссылки: Пример с раскрывающимся списком по умолчанию и раскрывающимся списком в виде кнопки: Вы также можете использовать ℹ️ Это экспериментальный синтаксис. В этой версии выпадающее меню срабатывает при наведении. Код с лицензией MIT Довольно распространенным видом навигации является раскрывающееся меню , в котором списки поднавигации появляются только тогда, когда курсор проходит по ссылке. HTML Dog имеет долгую историю с выпадающими списками — мы выделили популярный метод Suckerfish Dropdowns еще в 2003 году. Однако с тех пор стандарты и браузеры прошли долгий путь, и теперь мы можем безопасно использовать гораздо более простую технику, используя CSS без необходимости. для любого JavaScript. Прежде чем начать, подумайте, не будет ли разумнее всего применить раскрывающиеся списки к вашему сайту. Хотя скрытие основной части навигации может сделать дизайн более чистым, это добавляет пользователю дополнительный уровень сложности при переходе к этим скрытым ссылкам. Это не будет существенной проблемой для большинства, но будет для тех, кто не использует или не может использовать указывающее устройство, такое как мышь. Это может быть случай для людей с двигательными или зрительными нарушениями или для тех, кто использует мобильные устройства с сенсорным экраном. Вы должны, по крайней мере, подумать о том, как предоставить этим пользователям возможность навигации (см. пункты об использовании ссылок позже). Если вы решили использовать раскрывающиеся списки, давайте двигаться вперед и применять их наилучшим образом… Новый раздел примеров! Посмотрите весь этот код в действии и поэкспериментируйте с ним. Как и любая хорошая навигация, списков ссылок — лучший вариант для структурирования раскрывающихся списков. Так как мы хотим, чтобы один элемент раскрывал группу подэлементов, нам наверняка нужно вложенных списков , то есть список списков: Итак, у нас есть «Птицы» и «Млекопитающие» в качестве предметов верхнего уровня, а «Крысы», «Однопроходные» и так далее в качестве предметов второго уровня, подкатегории. Используйте ссылки. Всегда используйте ссылки. Если вас больше всего интересуют подкатегории (например, «Крысоловы» и «Однопроходные»), подумайте, по крайней мере, о том, чтобы основные элементы (например, «Птицы» и «Млекопитающие») ссылались на страницу со стандартной навигацией. на страницы подкатегорий. Основная причина этого — доступность — как уже отмечалось, посетители вашей страницы не всегда будут использовать указывающее устройство (которое, конечно, требуется для наведения и открытия подменю). Чтобы настроить все это визуально, давайте обнулим отступы по умолчанию (и поля для старых браузеров) списков: Далее, для каждого элемента списка мы хотим расположить их горизонтально. Забегая вперед, мы также хотим указать, что источником для позиционирования всех подсписков является их родительский элемент списка: Теперь займемся списками внутри списка. Мы хотим расположить их абсолютно, размещая их поверх всего, и мы хотим их скрыть: Чтобы приспособиться к более старым браузерам, вы также можете явно расположить подсписки, добавив к этому Наконец, чтобы показать эти подсписки при наведении курсора на элемент основного списка: Первый сопровождающий пример показывает это в действии вместе с поясняющими встроенными комментариями (см. исходный код). Размещение более одного уровня раскрывающегося меню потребует большего вложения списка: Теперь, чтобы немного по-другому относиться к этим новым под-подспискам, мы хотим, чтобы они отображались сбоку от своих элементов родительского списка, а не под ними: Нужна небольшая поправка. В его нынешнем виде будут показаны все списков потомков элемента списка, на который наведен курсор. Таким образом, при наведении курсора на «Млекопитающие» в этом примере будут показаны не только «Однопроходные», «Сумчатые» и «Плацентарные», но и все виды сумчатых — «Оппоссумы» и так далее. Нам нужен только первый потомок — детей (не внуков) — показать. Поэтому мы изменяем Другие базовые изменения, которые вы, возможно, захотите внести, включают плавающие элементы списка вместо использования Третий сопровождающий пример немного украшает ситуацию. Варианты презентаций, конечно, за вами, но это дает пищу для размышлений. Выделение списков родителей — это всегда хороший способ дать дополнительную подсказку о том, где вы находитесь. Переходы предлагают дополнительное преимущество, заключающееся в том, что выпадающие списки остаются немного дольше, уменьшая проблему неистово исчезающих списков, когда курсор на мгновение выходит за границы выпадающего списка. < тип = "радио" >
или < ввод тип > 010 09 90 909 Выбрать один элемент
Выбрать несколько элементов -- 2-03
--!
< детали роль = "список" >
< резюме aria-haspopup = "список" >Dropdown резюме >
< ul роль = "список" >
< ли >
< этикетка для = "маленький" >
< ввод тип = "радио" идентификатор = "маленький" имя = "размер" значение
7 =
>0008 "маленький
Маленький
метка >
ли >
< ли >
< этикетка для = "средний" >
< ввод тип = "радио" идентификатор = "средний" имя = "размер" значение = "09" >
Середина
метка >
ли >
< ли >
< ярлык для = "большой" >
< ввод тип = "радио" идентификатор = "большой" имя = "размер" значение = "большой" >
Большой
< 0 nav
< ул >
< li >< li >Марка li > li >
ул >
< ул >
< li >< a href = "#" >Ссылка a > li >
< ли >
< детали роль = "список" каталог = "rtl" >
< сводка aria-haspopup = "список" роль = "ссылка" >Dropdown резюме >
< ul роль = "список" >
< li >< a >Действие a > li >
< li >< a >Другое действие a > li >
< li >< a >Что-то еще здесь a > ли >
ул >
подробности >
ли >
ул >
nav >
< nav >
< ул >
< ли >
< детали роль = "список" >
< резюме aria-haspopup = "список" >Раскрывающийся список сводка >
< ul роль = "список" >
< li >< a >Действие a > li >
< li >< a >Другое действие a > li >
< li >< a >Что-то еще здесь a > li >
ул >
подробности >
ли >
< ли >
< детали роль = "список" >
< резюме aria-haspopup = "список" роль = "кнопка" >Dropdown резюме >
< ul роль = "список" >
< li >< a >Действие a > ли >
< li >< a >Другое действие a > li >
< li >< a >Что-то еще здесь a > li >
ул >
подробности >
ли >
ул >
nav >
< li роль = "список" >
в качестве вложенной оболочки для отображения списка в виде раскрывающегося списка. < навигация >
< ул >
< li >< li >Марка li > li >
ул >
< ул >
< li >< a href = "#" >Ссылка a > li >
< li >< a href = "#" >Ссылка a > li >
< li роль = "список" каталог = "rtl" >
< a href = "#" aria-haspopup = "listbox" >Dropdown a >
< ул роль = "список" >
< li >< a >Действие a > li >
< li >< a >Другое действие a > li >
< li >< a >Что-то еще здесь a > li >
ул >
ли >
ул >
nav >
Раскрывающиеся списки CSS | HTML Dog
HTML: красивые вложенные списки
<ул>
CSS: самое необходимое
ул {
заполнение: 0;
маржа: 0;
}
ли {
дисплей: встроенный;
положение: родственник;
}
уль уль {
положение: абсолютное;
дисплей: нет;
}
слева: 0
и сверху: 100%
.
ли: наведите ул {
дисплей: блок;
}
Многоуровневые раскрывающиеся списки
ул уль уль {
слева: 100%;
сверху: 0;
}
li:hover ul
, вставляя дочерний селектор :
li: наведите курсор > ул {
дисплей: блок;
}
display: inline
. Затем вы можете контролировать такие вещи, как ширина. Во втором сопровождающем живом примере применяются многоуровневые выпадающие списки и вносятся некоторые из этих основных улучшений. Очень красивая