- PVSM.RU - https://www.pvsm.ru -
Когда мы начинаем работать с адаптивным дизайном, мы сталкиваемся с различными техниками того, как лучше обработать изменение нашего навигационного меню для экранов с низким разрешением. Возможности кажутся бесконечными. Поэтому, я покажу вам четыре главных подхода с их достоинствами и недостатками. Три из них сделаны с использованием только CSS и один — с небольшим количеством JavaScript.
В коде, представленном в статье, я не использую браузерные префиксы, чтобы код стилей оставался простым к прочтению и пониманию. В более сложных примерах используется SCSS. Каждый из примеров размещен на сайте CodePen [1], где вы можете увидеть скомпилированный CSS.
Все подходы в этой статье используют простой HTML код, который я называю «базовое меню». Атрибут role [2] используется чтобы указать определенный тип: горизонтальное меню (full-horizontal), выпадающий список (select), ниспадающее меню (custom-dropdown) и canvas.
<nav role="">
<ul>
<li><a href="#">Stream</a></li>
<li><a href="#">Lab</a></li>
<li><a href="#">Projects</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
Для стилей я использую один и тот же медиа запрос [3] для всех вариантов:
@media screen and (max-width: 44em) {
}
Самый простой подход, потому что вам нужно лишь сделать список элементов шириной во всю страницу:
<nav role="full-horizontal">
<ul>
<li><a href="#">Stream</a></li>
<li><a href="#">Lab</a></li>
<li><a href="#">Projects</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
@media screen and (max-width: 44em) {
nav[role="full-horizontal"] {
ul > li {
width: 100%;
}
}
}
С дополнительным оформлением так оно выглядит на экранах с небольшим разрешением:
Пример горизонтального меню [4] можно увидеть на сайте CodePen.
В данном подходе скрывается базовое меню и показывается выпадающий список [5] вместо него.
Чтобы добиться такого эффекта нам нужно добавить в базовую разметку выпадающий список. Чтобы он работал нам придется добавить JavaScript код, который изменяет значение window.location [6].href когда происходит событие onchange [7]
<nav role="select">
<!-- basic menu goes here -->
<select onchange="if (this.value) window.location.href = this.value;">
<option value="#">Stream</option>
<option value="#">Lab</option>
<option value="#">Projects</option>
<option value="#">About</option>
<option value="#">Contact</option>
</select>
</nav>
Скрываем список на больших экранах:
nav[role="select"] {
> select {
display:none;
}
}
На маленьких экранах скрываем базовое меню и показываем выпадающий список. Чтобы помочь пользователю понять, что это меню — мы добавим псевдо-элемент с тектом «Меню»
@media screen and (max-width: 44em) {
nav[role="select"] {
ul {
display: none;
}
select {
display: block;
width: 100%;
}
&:after {
position: absolute;
content: "Menu";
right: 0;
bottom: -1em;
}
}
}
С дополнительным оформлением так оно выглядит на экранах с небольшим разрешением:
Пример этого меню [8].
В данном подходе на небольших экранах скрывается базовое меню и показывается input и label вместо них (используется хак с чекбоксом [9]). Когда пользователь кликает на label, базовое меню показывается под ним.
<nav role="custom-dropdown">
<!-- Advanced Checkbox Hack (see description below) -->
<!-- basic menu goes here -->
</nav>
Две основных проблемы с этим решением:
+
и ~
h1 ~ p { color: black; }
h1:hover ~ p { color: red; }
Это не оказывало никакого эффекта, потому что хак с чекбоксом использовал псевдокласс :checked
с селектором ~
. И пока баг не был исправлен в WebKit 535.1 (Chrome 13) и в актуальном для Android 4.1.2 WebKit 534.30, хак не работал ни на каком устройстве с ОС Android.
Лучшее решение [11] — это использовать анимацию только для WebKit-браузеров для тега <body>
Комбинация всех вариантов создает расширенный хак для чекбоксов [12]:
<!-- Fix for iOS -->
<input type="checkbox" id="menu">
<label for="menu" onclick></label>
/* Fix for Android */
body {
-webkit-animation: bugfix infinite 1s;
}
@-webkit-keyframes bugfix {
from { padding: 0; }
to { padding: 0; }
}
/* default checkbox */
input[type=checkbox] {
position: absolute;
top: -9999px;
left: -9999px;
}
label {
cursor: pointer;
user-select: none;
}
Для больших экранов мы скрываем label:
nav[role="custom-dropdown"] {
label {
display: none;
}
}
Для небольших экранов мы скрываем базовое меню и показываем label. Чтобы помочь пользователю понять, чтобы это меню, мы добавим псевдоэлемент с текстом "≡" в label (представим в виде кода "2261", чтобы использовать как содержимое псевдоэлемента). Когда пользователь кликает на input, базовое меню показывается и список элементов раскрывается во всю ширину.
@media screen and (max-width: 44em) {
nav[role="custom-dropdown"] {
ul {
display: none;
height: 100%;
}
label {
position: relative;
display: block;
width: 100%;
}
label:after {
position: absolute;
content: "2261";
}
input:checked ~ ul {
display: block;
> li {
width: 100%;
}
}
}
}
Так меню выглядит на маленьких экранах:
Пример работы этого меню [13].
В этом подходе, на небольших экранах, скрывается базовое меню и показывается input и label как в варианте 3. Когда пользователь кликает на label, базовое меню выплывает слева и содержимое перемещается вправо. Экран разделяется на части в пропорциях 80% меню и 20% содержимое (в зависимости от разрешения и единиц, используемых в CSS)
<input type="checkbox" id="menu">
<label for="menu" onclick></label>
<!-- basic menu goes here -->
<div class="content">
<!-- content goes here -->
</div>
На больших экранах мы скрываем label.
label {
position: absolute;
left: 0;
display: none;
}
На маленьких экранах мы помешаем меню вне содержимого окна и показываем label и input. Чтобы скрыть меню мы устанавливаем для него ширину и отрицательное значение положения. Чтобы помочь пользователю понять, чтобы это меню, мы так же добавим псевдоэлемент с текстом "≡" в label (в виде кода "2261", чтобы использовать как содержимое псевдоэлемента).
@media screen and (max-width: 44em) {
$menu_width: 20em;
body {
overflow-x: hidden;
}
nav[role="off-canvas"] {
position: absolute;
left: -$menu_width;
width: $menu_width;
ul > li {
width: 100%;
}
}
label {
display: block;
}
label:after {
position: absolute;
content: "2261";
}
input:checked ~ nav[role="off-canvas"] {
left: 0;
}
input:checked ~ .content {
margin-left: $menu_width + .5em;
margin-right: -($menu_width + .5em);
}
}
С дополнительным оформлением так оно выглядит на экранах с небольшим разрешением:
Пример этого меню [14].
Все использованные техники преследуют одну цель: создать адаптивное меню для современных браузеров! И все потому, что нет никаких IE8 или ниже ни на каких мобильных устройствах и, поэтому, мы можем совершенно не беспокоиться об этом вопросе.
Автор: druf
Источник [15]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/tutorial/20501
Ссылки в тексте:
[1] CodePen: http://codepen.io/
[2] Атрибут role: http://www.w3.org/TR/xhtml-role/
[3] медиа запрос: https://developer.mozilla.org/en-US/docs/CSS/Media_queries
[4] Пример горизонтального меню: http://codepen.io/TimPietrusky/pen/ysblx
[5] выпадающий список: https://developer.mozilla.org/en-US/docs/HTML/Element/select
[6] window.location: https://developer.mozilla.org/en-US/docs/DOM/window.location
[7] onchange: https://developer.mozilla.org/en-US/docs/DOM/element.onchange
[8] Пример этого меню: http://codepen.io/TimPietrusky/pen/iopIJ
[9] хак с чекбоксом: http://css-tricks.com/the-checkbox-hack/
[10] добавлением пустого события: http://stackoverflow.com/questions/5421659/html-label-command-doesnt-work-in-iphone-browser/6472181#6472181
[11] Лучшее решение: http://stackoverflow.com/questions/8320530/webkit-bug-with-hover-and-multiple-adjacent-sibling-selectors/8320736#8320736
[12] расширенный хак для чекбоксов: http://timpietrusky.com/advanced-checkbox-hack
[13] Пример работы этого меню: http://codepen.io/TimPietrusky/pen/gqlhA
[14] Пример этого меню: http://codepen.io/TimPietrusky/pen/CLIsl
[15] Источник: http://habrahabr.ru/post/159359/
Нажмите здесь для печати.