Меняющееся гамбургер меню на CSS

Луис Мануэль

Оригинал: scotch.io/tutorials/building-a-morphing-hamburger-menu-with-css
Перевод: Влад Мержевич

Недавно я обнаружил эту потрясающую картинку на dribbble.com от Виталия Рубцова и не мог удержаться от желания её реализовать.

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

Вот пример того, что мы будем делать:

Разметка

Начнём со структуры HTML, которую мы будем использовать. Смотри комментарии для лучшего понимания.

HTML

<div class="container">
 <!-- Этот чекбокс даст нам поведение переключателя, 
  он будет скрыт, но работать -->
 <input id="toggle" type="checkbox">
 <!-- ВАЖНО: любой элемент, который мы хотим модифицировать при изменении 
  состояния чекбокса, является «братским» элементом для чекбокса -->
 <!-- Эта метка привязана к чекбоксу и будет содержать переключение «кнопок» -->
 <label class="toggle-container" for="toggle">
 <!-- Если меню открыто, то здесь будет иконка «X», 
  в противном случае просто иконка гамбургера -->
  <span class="button button-toggle"></span>
 </label>
 <!-- Навигация -->
 <nav class="nav">
  <a class="nav-item" href="">Управление</a>
  <a class="nav-item" href="">История</a>
  <a class="nav-item" href="">Статистика</a>
  <a class="nav-item" href="">Настройки</a>
 </nav>
</div>

Начальные стили SCSS

Теперь добавим некоторые базовые стили, чтобы получить желаемый внешний вид. Код довольно простой.

SCSS

/* Базовые стили */
* {
  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 уже на месте. А стиль, который заставляет его работать, примерно такой:

SCSS

// Прячем чекбокс
#toggle {
  display: none;
}

// Стили для «открытого» состояния, когда чекбокс выбран
#toggle:checked {
// Любой элемент, стиль которого вам нужно изменить при открытии меню, идёт здесь с  селектором ~
  // Стили для открытия навигационного меню, к примеру
  & ~ .nav {
  }
}

Создание закрытого состояния

Чтобы сделать закрытое состояние, нам нужно преобразовать пункты меню в линии, чтобы получить иконку гамбургера. Есть несколько путей для получения такой трансформации. Мы решили сделать это следующим образом:

И вот код, который это реализует.

SCSS

$transition-duration: 0.5s;
// Отображение пунктов навигации в виде линий, составляющих иконку гамбургера
.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;

  // Добавление ширины для первой линии
  &:nth-child(1) {
    letter-spacing: -8px;
  }

  // Добавление ширины для второй линии
  &:nth-child(2) {
    letter-spacing: -7px;
  }

  // Настройки для элементов, начиная с четвёртого
  &:nth-child(n + 4) {
    letter-spacing: -8px;
    margin-top: -7px;
    opacity: 0;
  }

  // Получение линий для иконки гамбургера
  &:before {
    position: absolute;
    content: '';
    top: 50%;
    left: 0;
    width: 100%;
    height: 2px;
    background-color: #EC7263;
    transform: translateY(-50%) scaleY(5);
    transition: $transition-duration;
  }
}

Обратите внимание, что здесь мы разместили только основные стили для пунктов навигации, который наиболее важны. Вы можете найти полный код на Github.

Создание открытого меню

Чтобы создать открытое меню, нам необходимо восстановить пункты навигации из линий в обычные текстовые ссылки, а также проделать ряд мелких изменений. Давайте посмотрим, как это сделать:

SCSS

$transition-duration: 0.5s;
#toggle:checked {

  // Открываем
  & ~ .nav {
    // Восстанавливаем пункты навигации из «линий» в иконке меню
    .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;
  
      // Скрываем линии
      &:before {
        opacity: 0;
      }
    }
  }
}

Магия в мелочах

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

SCSS

$items: 4;
$transition-delay: 0.05s;

.nav-item {
  // Задаём задержку для пунктов навигации при закрытии
  @for $i from 1 through $items {
    &:nth-child(#{$i}) {
      $delay: ($i - 1) * $transition-delay;
      transition-delay: $delay;
      &:before {
        transition-delay: $delay;
      }
    }
  }
}

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

Обратите внимание, что с помощью этого кода мы получим желаемое пошаговое поведение для анимации закрытия. Нам нужно вычислить $delay, немного отличающийся для анимации открытия, чтобы получить обратно ступенчатый переход. Вроде этого:

SCSS

$delay: ($items - $i) * $transition-delay;

Вывод

Вот мы и закончили с нашим причудливым меню! Мы также включили некоторые фиктивные элементы как в анимированном gif, и вы можете увидеть финальную демонстрацию здесь.

Итак, мы создали простое и функциональное меню только на CSS. Однако, если вы не хотите использовать систему переключения CSS, она может быть идеально заменена с помощью нескольких строк JavaScript без особых усилий.

Вы можете найти полный код в хранилище Github, а также поиграть с кодом напрямую на Codepen.

Надеемся, этот урок оказался вам по душе и вы сочли его полезным!

Не выкладывайте свой код напрямую в комментариях, он отображается некорректно. Воспользуйтесь сервисом cssdeck.com или jsfiddle.net, сохраните код и в комментариях дайте на него ссылку. Так и результат сразу увидят.