Построение Morphing Hamburger Menu только на CSS

Недавно я наткнулся на dribbble Виталия Рубцова, и я не смог устоять перед желанием реализовать его Morphing Hamburger Menu исключительно на CSS. Это меню легко можно использовать при создании дизайна интерфейса мобильных приложений и сайтов.

Построение Morphing Hamburger Menu только на CSS

В этом уроке я покажу весь процесс, как это сделать только с помощью CSS, не используя не единой строчки JavaScript. Вы увидите некоторые трюки CSS (и SCSS), которые позволяют достичь анимации такой же плавной, как анимированный GIF.

Пример из CodePen того что мы будем делать

Начнём с HTML. Для понимания что для чего читайте комментарии.

Теперь добавляем базовые стили для придания необходимого нам внешнего вида.
/* Basic styles */

* {
box-sizing: border-box;
}

html, body {
margin: 0;
}

body {
font-family: sans-serif;
background-color: #F6C390;
}

a {
text-decoration: none;
}

.container {
position: relative;
margin: 35px auto 0;
width: 300px;
height: 534px;
background-color: #533557;
overflow: hidden;
}

Перед тем как начать строить остальную часть интерфейса, давайте добавим функциональные возможности лёгкого переключения из одного состояния в другое. Нужный нам HTML уже на есть, а стиль, чтобы всё работало может быть чем-то вроде этого:
// To hide the checkbox
#toggle {
display: none;
}

// Styles for the 'open' state, if the checkbox is checked
#toggle:checked {
// Any element you need to change the style if menu is open goes here, using the sibling selector (~) as follows

// Styles for the open navigation menu, for example
& ~ .nav {
}
}

Теперь нам нужно преобразовать пункты меню в линии, чтобы создать значок меню гамбургер. Это можно сделать несколькими способами, мы сделаем это так:
Построение Morphing Hamburger Menu только на CSS

И вот код для работы всего что мы задумали:
$transition-duration: 0.5s;

// Showing nav items as lines, making up the hamburger menu icon
.nav-item {
position: relative;
display: inline-block;
float: left;
clear: both;
color: transparent;
font-size: 14px;
letter-spacing: -6.2px;
height: 7px;
line-height: 7px;
text-transform: uppercase;
white-space: nowrap;
transform: scaleY(0.2);
transition: $transition-duration, opacity 1s;

// Adjusting width for the first line
&:nth-child(1) {
letter-spacing: -8px;
}

// Adjusting width for the second line
&:nth-child(2) {
letter-spacing: -7px;
}

// Adjusting from the fourth element onwards
&:nth-child(n + 4) {
letter-spacing: -8px;
margin-top: -7px;
opacity: 0;
}

// Getting the lines for the hamburger menu icon
&:before {
position: absolute;
content: '';
top: 50{33d8302486bd10b0fde64d2037652320e6f176a736d71849c0427b0d7398501a};
left: 0;
width: 100{33d8302486bd10b0fde64d2037652320e6f176a736d71849c0427b0d7398501a};
height: 2px;
background-color: #EC7263;
transform: translateY(-50{33d8302486bd10b0fde64d2037652320e6f176a736d71849c0427b0d7398501a}) scaleY(5);
transition: $transition-duration;
}
}

Обратите внимание, что здесь мы разместили только основные стили для элементов nav, которые являются наиболее важной частью. Полный код на GitHub.

Чтобы построить открытое меню нам нужно переделать nav элементы из линий в текстовые ссылки, добавив незначительные изменения. Давайте посмотрим, как это сделать:
$transition-duration: 0.5s;

#toggle:checked {

// Open nav
& ~ .nav {

// Restoring nav items from "lines" in the menu icon
.nav-item {
color: #EC7263;
letter-spacing: 0;
height: 40px;
line-height: 40px;
margin-top: 0;
opacity: 1;
transform: scaleY(1);
transition: $transition-duration, opacity 0.1s;

// Hiding the lines
&:before {
opacity: 0;
}
}
}
}

Если внимательно посмотреть на gif, мы увидим, что элементы меню не двигаются одновременно, а выдвигаются по очереди. Это реализуется тоже с помощью CSS. Мы должны выбрать каждый элемент (с помощью: nth-child) и установить задержку постепенно увеличивая. Но это, конечно, монотонная работа. Вы зададите резонный вопрос: а что если мы имеем больше элементов? Не волнуйтесь, мы можем сделать это лучше добавив немного SCSS-магии:
$items: 4;
$transition-delay: 0.05s;

.nav-item {

// Setting delays for the nav items in close transition
@for $i from 1 through $items {
&:nth-child(#{$i}) {
$delay: ($i - 1) * $transition-delay;
transition-delay: $delay;
&:before {
transition-delay: $delay;
}
}
}
}

Здесь мы используем цикл, переменную интерполяции и некоторые основные арифметические операции. Вы можете ознакомиться с этими и многими другими штуками более подробно в документации сайта SASS.

Обратите внимание, что с помощью этого кода мы получим желаемое ступенчатое поведение для анимации. Нам нужно вычислить $delay для открытия, чтобы получить обратный переход, сделаем это так:
$delay: ($items - $i) * $transition-delay;

Ну и собственно, наше меню готово. Нужно ещё добавить несколько элементов заглушек, как на анимированном gif в начале статьи, результат можно посмотреть в DEMO

Итак, мы смогли сделать крутое функциональное меню, без единой строки js, как и обещали в начале. Если вам не нравится использовать чистый css, всё это вы легко можете заменить несколькими строками JavaScript.

Надеюсь вам оказалась полезна эта статья.

Источник на английском: https://scotch.io/

Leave a Comment