Какой должна быть логика реализации выпадающего меню с возможностью перехода как на корневую страницу, так и на вложенные?
Имеется меню, где есть корневые страницы, и у некоторых из них - дочерние в виде выпадающего подменю:
.navbar {
display: flex;
list-style: none;
padding: 0;
}
.navbar a:hover {
opacity: .7;
}
.navbar > li a {
padding: 15px;
}
.has-sub-menu {
position: relative;
}
.sub-menu {
padding: 0;
position: absolute;
white-space: nowrap;
list-style: none;
padding-top: 10px;
opacity: 0;
pointer-events: none;
}
.has-sub-menu a:hover + .sub-menu,
.sub-menu:hover {
opacity: 1;
pointer-events: auto;
}
<nav>
<ul class="navbar">
<li><a href="#">О компании</a></li>
<li class="has-sub-menu">
<a href="#">Проекты</a>
<ul class="sub-menu">
<li><a href="#">Проект А</a></li>
<li><a href="#">Проект В</a></li>
<li><a href="#">Проект С</a></li>
</ul>
</li>
<li><a href="#">Контакты</a></li>
</ul>
</nav>
Проблемы с ним две:
1. На десктопах выпадайки появляются при наведении, и пользователь может перейти на дочерние страницы. Но для перехода на корневую по пункту меню нужно кликнуть, что совершенно не очевидно.
2. На тачскринах, где ховера по сути нет, а есть только клик, пользователя сразу перебрасывает на корневую (при этом на долю секунды показывается, а потом скрывается выпадайка, что вообще выглядит как баг)
Как подружить между собой эти два варианта взаимодействия с меню? Возможно, одним css не обойтись, и нужен js? Не прошу за меня писать код, прошу помощи с логикой реализации.
Ответы (1 шт):
На десктопах выпадайки появляются при наведении, и пользователь может перейти на дочерние страницы. Но для перехода на корневую по пункту меню нужно кликнуть, что совершенно не очевидно.
раз уж кликабельность заголовка не очевидна, так пусть он и будет только лишь заголовком меню\триггером события. ссылку же спрятать внутрь меню.
На тачскринах, где ховера по сути нет, а есть только клик, пользователя сразу перебрасывает на корневую
есть и другие... как бы это правильней назвать... "состояния" пожалуй.
*:active, *:focus
. второй из них прекрасно подходит для подобных целей
#abc {
display: grid;
grid-template: 4em / repeat(4, auto);
}
li:not(:first-child){
display: none;
}
#w:active > *{
display: list-item;
background: skyblue;
border: 5px solid blue;
}
#x:focus > *,
#y:focus > *{
display: list-item;
background: pink;
border: 5px solid violet;
}
#z:hover > *{
display: list-item;
background: green;
border: 5px solid lime;
}
ol{background: gray;}
ol > *{
border-radius: .5em;
padding: .2em;
}
<div id='abc'>
<ol id='w'>
<li>#w:active</li>
<li>тригерится на зажатие мыши\долгий тап</li>
<li>для такой задачи конечно бесполезен</li>
<li>но для ознакомления не будет лишним</li>
</ol>
<ol id='x'>
<li>#x:focus</li>
<li>сам по себе фокус не применяется</li>
<li>к чему то кроме инпутов, кнопок и т.п.</li>
</ol>
<ol id='y' tabindex='1'>
<li>#y:focus + tabindex</li>
<li>но если добавить контейнеру</li>
<li><i>tabindex</i>, то уже всё норм</li>
<li><button onclick='blur()'>закрыть можно вызвав blur()</button></li>
<li>либо кликнув\тапнув мимо контейнера</li>
</ol>
<ol id='z'>
<li>#z:hover</li>
<li>ну и ховер для сравнения</li>
</ol>
</div>