Подходы к реализации адаптивного меню

от автора

Когда мы начинаем работать с адаптивным дизайном, мы сталкиваемся с различными техниками того, как лучше обработать изменение нашего навигационного меню для экранов с низким разрешением. Возможности кажутся бесконечными. Поэтому, я покажу вам четырые главных подхода с их достоинствами и недостатками. Три из них сделанны с использованием только CSS и один — с небольшим количеством JavaScript.

image

Введение

В коде, представленном в статье, я не использую браузерные префиксы, чтобы код стилей оставался простым к прочтению и пониманию. В более сложных примерах испольуется SCSS. Каждый из примеров размещен на сайте CodePen, где вы можете увидеть скомпилированный CSS.

Все подходы в этой статье используют простой HTML код, который я называю «базовое меню». Атрибут role используется чтобы указать определенный тип: горизонтальное меню (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> 

Для стилей я использую один и тот же медиа запрос для всех вариантов:

@media screen and (max-width: 44em) {  } 

1. Горизонтальное меню

Самый простой подход, потому что вам нужно лишь сделать список элементов шириной во всю страницу:

<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%;     }   } } 

С дополнительным оформлением так оно выглядит на экранах с небольшим разрешением:
Горизонательное меню

Преимущества

  • Не требуется JavaScript
  • Никакой лишней разметки
  • Простой код стилей

Недостатки

  • Занимает слишком много места на экране

Пример горизонтального меню можно увидеть на сайте CodePen.

2. Выпадающий список

В данном подходе скрывается базовое меню и показывается выпадающий список вместо него.

Чтобы добиться такого эффекта нам нужно добавить в базовую разметку выпадающий список. Чтобы он работал нам придется добавить JavaScript код, который изменяет значение window.location.href когда происходит событие onchange

<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;     }   } } 

С дополнительным оформлением так оно выглядит на экранах с небольшим разрешением:
Выпадающий список

Преимущества

  • Не занимает много места
  • Использует «собственные» элементы управления
Недостатки

  • Для работы требуется JavaScript
  • Происходит дублирование контента
  • Выпадающий список не удается стилизовать во всех браузерах

Пример этого меню.

3. Пользовательское ниспадающее меню

В данном подходе на небольших экранах скрывается базовое меню и показывается input и label вместо них (используется хак с чекбоксом). Когда пользователь кликает на label, базовое меню показывается под ним.

<nav role="custom-dropdown">     <!-- Advanced Checkbox Hack (see description below) -->          <!-- basic menu goes here --> </nav> 

Проблемы с использованием хака с чекбоксом

Две основных проблемы с этим решением:

  1. Оно не работает на мобильных версиях Safari (iOS < 6.0). Невозможно кликнуть на label в браузере под iOS < 6.0, чтобы сработал input из-за бага. Решается добавлением пустого события onclick на label
  2. Оно не работает на основном браузере ОС Android версии меньше или равной 4.1.2. Давным давно был баг в WebKit движке, который не позволял использовать псевдо-классы с комбинацией селекторов + и ~
h1 ~ p { color: black; } h1:hover ~ p { color: red; } 

Это не оказывало никакого эффекта, потому что хак с чекбоксом использовал псевдокласс :checked с селектором ~. И пока баг не был исправлен в WebKit 535.1 (Chrome 13) и в актуальном для Android 4.1.2 WebKit 534.30, хак не работал ни на каком устройстве с ОС Android.

Лучшее решение — это использовать анимацию только для WebKit-браузеров для тега <body>

Комбинация всех вариантов создает расширенный хак для чекбоксов:

<!-- 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%;       }             }   } } 

Так меню выглядит на маленьких экранах:

Закрытое
Закрытое

Преимущества

  • Не занимает много места в закрытом состоянии
  • Целиком стилизуется
  • Не требует JavaScript

Недостатки

  • Не семантичный код (input / label)
  • Требуется дополнительный HTML

Пример работы этого меню.

4. Canvas

В этом подходе, на небольших экранах, скрывается базовое меню и показывается 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);   } } 

С дополнительным оформлением так оно выглядит на экранах с небольшим разрешением:

Закрытое
Открытое

Преимущества

  • Не занимает много места в закрытом состоянии
  • Целиком стилизуется
  • Не требует JavaScript
  • Работает как Facebook / Google+ приложения
Недостатки

  • Не семантичный код (input / label)
  • Требуется дополнительный HTML
  • Абсолютное позиционирование элемента body вызывает ощущение зафиксированного положения

Пример этого меню.

Работает ли это под IE?

Все использованные техники преследуют одну цель: создать адаптивное меню для современных браузеров! И все потому, что нит никаких IE8 или ниже ни на каких мобильных устройствах и, поэтому, мы можем совершенно не беспокоится об этом вопросе.

ссылка на оригинал статьи http://habrahabr.ru/post/159359/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *