От автора: Гамбургер-меню, выдвижное меню, off-canvas меню: как бы эту разновидность меню ни называли, скрытие основной навигации на сайте становится шаблоном, использующимся повсеместно в отзывчивом веб-дизайне. Все больше и больше сайтов используют зафиксированную иконку, при нажатии на которую весь сайт сдвигается в сторону, чтобы отобразить скрытое меню.
Несмотря на то, что существует огромное количество созданных для этого jQuery-плагинов, это достаточно легко можно реализовать и вовсе без использования JavaScript. В данной статье рассмотрен простой вариант создания скрытого меню и эффекта выдвижения с помощью одного CSS.
Прежде чем мы начнем, я хотел бы отметить, что при использовании данного метода для создания выдвижного меню навигация вашего сайта всегда будет скрыта, вне зависимости от размера окна просмотра. Если вы хотите, чтобы выдвижное меню появлялось только на маленьких экранах, тогда вам нужно будет немного задействовать JavaScript или использовать продвинутый CSS, чтобы ваше меню хорошо смотрелось на больших экранах. Другими словами: это легко и просто, но это не является единственно верным решением во всех ситуациях.
Вот демо-пример на сайте CodePen, показывающий конечный результат:
Начнем с HTML
Разметка для скрытого меню будет немного отличаться от варианта для стандартного меню навигации. Вместо того чтобы поместить меню внутри шапки сайта (header), мы поместим его сразу после открывающего тега body. Базовая структура выглядит так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<ul class="navigation"> <li class="nav-item"><a href="#">Главная</a></li> <li class="nav-item"><a href="#">Портфолио</a></li> <li class="nav-item"><a href="#">О нас</a></li> <li class="nav-item"><a href="#">Блог</a></li> <li class="nav-item"><a href="#">Контакты</a></li> </ul> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger"></label> <div class="site-wrap"> <!-- здесь идет вся остальная разметка страницы --> </div> |
Как видите, разметка нашего сайта состоит из трех основных элементов: навигация, чекбокс (checkbox) и парный тег label, а также непосредственно контент сайта. Здесь следует отметить несколько моментов:
Разметка навигации размещается в коде в первую очередь, т.к. навигации находится «позади» всех остальных элементов сайта. Для создания навигации вы можете использовать любые HTML-теги. В данном случае я использую привычный ненумерованный список.
Триггером для выдвижения нашего меню послужит тег input с типом checkbox и тег label. Обычно тег label располагается перед тегом input или тег input оборачивается тегом label. Но в данном случае тег input должен идти непосредственно перед тегом label. И далее, при добавлении CSS-стилей, мы увидим почему.
Все остальные элементы сайта должны быть обернуты в отдельный тег div. Это необходимо сделать для того, чтобы при открытии меню все остальное содержимое съезжало немного за границы экрана, чтобы показать скрытые элементы навигации.
Теперь, когда у нас есть базовая HTML структура, мы можем заняться внешним видом нашего меню!
CSS-стили для пунктов меню
Давайте начнем с добавления стилей для самого меню и его пунктов. Первым делом, нам необходимо убедиться в том, что наше меню находится под содержимым страницы и остается на месте, когда пользователь прокручивает страницу:
1 2 3 4 5 6 7 8 9 10 11 12 |
.navigation { list-style: none; background: #111; width: 100%; height: 100%; position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 0; } |
Далее, я добавил немного стилей для того чтобы наша навигация выглядела привлекательнее (фоновые цвета, границы, градиенты и т.д.). Не буду приводить здесь этот код, но вы можете посмотреть, как именно я это сделал, в демо-примере. Теперь у нас есть несколько симпатичных пунктов меню, но в целом это вовсе не здорово, т.к. наш контент расположился прямо на нашем меню. Давайте добавим стилей, чтобы спрятать меню до нужного момента.
CSS-стили для «обертки» сайта
Для начала, давайте убедимся в том, что содержимое сайта полностью скрывает наше меню. На этом этапе можно добавить несколько абзацев с «lorem ipsum» к нашему элементу с классом .site-wrap, если вы еще не добавили никакого контента.
1 2 3 4 5 6 7 8 9 10 |
.site-wrap { min-width: 100%; min-height: 100%; background-color: #fff; position: relative; top: 0; bottom: 100%; left: 0; z-index: 1; } |
Стоит заметить, что мы обязаны указать фон для элемента с классом .site-wrap, иначе меню будет проглядывать сквозь контент. Вы можете, конечно, установить любой фон, какой сами захотите. Лично я использовал следующий:
1 2 3 4 5 6 7 8 9 |
.site-wrap { /* ... предыдущие стили находятся здесь ... */ padding: 4em; background-image: linear-gradient(135deg, rgb(254,255,255) 0%, rgb(221,241,249) 35%, rgb(160,216,239) 100%); background-size: 200%; } |
CSS-стили для триггера меню
Следующим шагом будет добавление стилей для изменения внешнего вида триггера меню с обычного чекбокса на классическую иконку «гамбургер», которую мы все знаем и любим. Сначала, давайте спрячем сам чекбокс.
1 2 3 4 |
.nav-trigger { position: absolute; clip: rect(0, 0, 0, 0); } |
Примечание редактора: изначально, в данном коде использовалось свойство display: block вместе с указанием нулевого значения для ширины и высоты самого чекбокса, чтобы сделать его невидимым, но доступным (активным). Но оказалось, что такое сочетание стилей в операционной системе iOS приводило к сбою в работе браузера и его закрытию, каждый раз, когда меню открывалось. Я изменил эту технику и стал использовать вместо этого свойство clip, которое, похоже, имеет такой же уровень доступности.
Итак, мы прячем чекбокс, используя свойство clip, которое требует применения свойства position: absolute для заданного элемента. Теперь мы задаем стили для элемента label:
1 2 3 4 5 6 |
label[for="nav-trigger"] { position: fixed; top: 15px; left: 15px; z-index: 2; } |
Прежде всего, мы задаем свойство position: fixed, чтобы элемент оставался на прежнем месте при прокрутке страницы пользователем. Свойства top и left определяют, как далеко от края окна просмотра будет находиться иконка. Мы также должны убедиться в том, что значение для свойства z-index у триггера выше хотя бы на единицу, чем значение этого свойства для элемента с классом .site-wrap. Затем, мы добавляем еще стилей для того, чтобы сделать из элемента label иконку «гамбургер».
1 2 3 4 5 6 7 8 |
label[for="nav-trigger"] { /* ... предыдущие стили находятся здесь ... */ width: 30px; height: 30px; cursor: pointer; background-image: url("data:image/svg+xml;utf8,<svg xmlns='//www.w3.org/2000/svg' xmlns:xlink='//www.w3.org/1999/xlink' version='1.1' x='0px' y='0px' width='30px' height='30px' viewBox='0 0 30 30' enable-background='new 0 0 30 30' xml:space='preserve'><rect width='30' height='6'/><rect y='24' width='30' height='6'/><rect y='12' width='30' height='6'/></svg>"); background-size: contain; } |
Я использовал в качестве фонового изображения встроенный элемент SVG, но вы можете использовать любую другую иконку, включая использование псевдо-элементов :before и :after, чтобы переделать иконку «гамбургер» на чистом CSS. Обратите внимание, что я также добавил свойство cursor: pointer;, чтобы визуально выделить иконку при наведении.
CSS-стили, чтобы триггер стал активным
Теперь, когда задано оформление для нашего меню, «обертки» сайта и триггера, давайте добавим еще несколько строчек CSS, чтобы все окончательно заработало.
1 2 3 4 5 6 7 8 |
.nav-trigger:checked + label { left: 215px; } .nav-trigger:checked ~ .site-wrap { left: 200px; box-shadow: 0 0 5px 5px rgba(0,0,0,0.5); } |
Вторая часть из вышеприведенного блока со стилями гарантирует нам то, что «обертка» сайта вместе с содержимым будет отодвинута на 200 пикселей. Я также добавил тень (свойство box-shadow) для «обертки» сайта, что придаст дополнительное ощущение того, что она находится сверху меню.
Первый селектор (.nav-trigger:checked + label) контролирует расположение триггера при открытии меню. Вам нужно будет прибавить число, которое мы использовали ранее для label[for=»nav-trigger»], к тому значению, которое отвечает за то, на какое расстояние «обертка» сайта будет отодвигаться. В данном случае это: 15px + 200px = 215px.
Вот когда становится важным порядок следования элементов триггера в коде. Второй селектор использует символ ~ для управления родственными элементами, чтобы указать на элемент с классом .site-wrap, когда элемент с классом .nav-trigger будет активным. Порядок следования в коде тега input с типом checkbox здесь не так важен.
Однако, мы должны указать и на элемент с классом .site-wrap и на наш тег label, основываясь на том, будет наш чекбокс активным или нет. Для этого, мы используем + (селектор соседних элементов), чтобы указать на элемент label, который следует за активным чекбоксом. Если бы мы сначала указали тег label, тогда у нас бы не было никакой возможности передвигать его вместе с «оберткой» сайта при активации триггера.
В качестве завершающего штриха мы можем добавить CSS-переход (transition) и для триггера и для «обертки» сайта, чтобы открытие нашего меню сопровождалось плавной анимацией. Только убедитесь в том, что вы указали в свой варианте необходимые вендорные префиксы или использовали что-то наподобие плагина Autoprefixer.
1 2 3 |
.nav-trigger + label, .site-wrap { transition: left 0.2s; } |
Один последний момент: используйте свойство overflow, чтобы избежать выхода контента у элемента body за границы окна просмотра по оси x. Если вы этого не сделаете, тогда у пользователей появится горизонтальная полоса прокрутки при открытии меню.
1 2 3 |
body { overflow-x: hidden; } |
Конечный результат
Вот и все! Мы успешно создали скользящее скрытое меню без использования JavaScript. И снова даю ссылку на демо-пример на сайте CodePen, чтобы продемонстрировать вам конечный результат:
Теперь, когда вы знаете, как это делается, не стесняйтесь поэкспериментировать с этой идеей. Создайте меню, которое будет выдвигаться справа, или же сделайте сайт с двумя меню (слева и справа).
Мне бы очень хотелось увидеть, что у вас получилось, поэтому поделитесь ссылкой на сайт CodePen с вашим примером в комментариях, или ссылками на другие примеры скрытого меню на чистом CSS.
Автор: Austin Wulf
Источник: //www.sitepoint.com/
Редакция: Команда webformyself.
Комментарии (13)