Как стать автором
Обновить
167.37
Beget
Beget — международный облачный провайдер

Меню для отзывчивого интерфейса без скриптов

Уровень сложностиСредний
Время на прочтение12 мин
Количество просмотров1.5K
Автор оригинала: Ivy Walobwa

Простое и понятное меню навигации — важнейшая часть удобного интерфейса. Отзывчивость меню тоже критична, ведь сейчас более половины всего интернет-трафика приходится на мобильные устройства.
В подходе mobile-first разработка начинается с самого маленького экрана — мобильного, и по мере увеличения ширины добавляются новые стили и элементы. В итоге страница автоматически подстраивается под размер окна браузера.
Хотя адаптивное меню — ключевой элемент хорошего UX, для его реализации не обязательно использовать JavaScript. В этом руководстве мы покажем, как сделать отзывчивое mobile-first меню только с помощью HTML и CSS.

Отзывчивое меню на чистом CSS

Существует много способов реализации мобильного меню, и один из самых популярных — с использованием только CSS, без JavaScript. В основе — обычный HTML-список ссылок, стилизованный под размер экрана.
В этом уроке мы с помощью CSS создадим меню навигации, которое работает на мобильных устройствах, планшетах и десктопах:

Меню на экране смартфона
Меню на экране смартфона
Меню на планшете
Меню на планшете
Меню на десктопе
Меню на десктопе

На небольших экранах меню будет скрыто за иконкой. А на больших — его пункты сразу будут видны в панели навигации.
Весь функционал будет реализован только на HTML и CSS, включая иконку меню. Наш результат будет выглядеть так:

Menu on mobile.
Menu on mobile.

Начнем с подготовки файлов

Создайте в одной папке два файла в любом удобном редакторе:

  • index.html — для HTML-кода

  • style.css — для CSS-кода

Затем откройте файл index.html в браузере, чтобы видеть изменения.

Начинаем с HTML-кода

Добавьте в файл index.html следующий код:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- App title -->
    <title>Responsive Pure CSS Menu</title>
    <!-- Link CSS file -->
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <!-- Navigation bar -->
    <header class="header">
        <!-- Logo -->
        <a href="#" class="logo">LR</a>
        <!-- Hamburger icon -->
        <input class="side-menu" type="checkbox" id="side-menu"/>
        <label class="hamb" for="side-menu"><span class="hamb-line"></span></label>
        <!-- Menu -->
        <nav class="nav">
            <ul class="menu">
                <li><a href="#">Gallery</a></li>
                <li><a href="#">Blog</a> </li>
                <li><a href="#">About</a></li>
            </ul>
        </nav>
    </header>
    <!-- Main content -->
    <main>
        <article>
            <h1>
                Some content
            </h1>
            <p>
                More Content
            </p>
        </article>
    </main>
</body>
</html>

Этот код задаёт структуру и содержимое веб-страницы, подключает таблицу стилей CSS и делит панель навигации и основной контент с помощью семантических элементов header и main. Также добавляется логотип с помощью элемента привязки <a>.
Для иконки меню мы используем элемент checkbox — с его помощью можно менять стиль в зависимости от состояния флажка.
Мы используем элемент label, чтобы обозначить иконку меню, а input с классом side-menu будет определять, отображается меню или нет. Пункты меню добавляются как элементы <li> внутри неупорядоченного списка ul, который, в свою очередь, находится в контейнере nav.

Вот результат после добавления HTML-кода:

Добавляем CSS-оформление

Теперь с помощью CSS мы стилизуем содержимое страницы и все элементы интерфейса.

Стилизация фона и основного содержимого

Добавим в файл style.css следующий код:

/* Theming */
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap"); /* import font */

:root{
    --white: #f9f9f9;
    --black: #36383F;
    --gray: #85888C;
} /* variables*/

/* Reset */
*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body{
    background-color: var(--white);
    font-family: "Poppins", sans-serif;
}
a{
    text-decoration: none;
}
ul{
    list-style: none;
}

Этот код вызывает загрузку шрифта Poppins Google и задаёт переменные CSS для используемых цветов. Затем мы добавляем CSS, чтобы сделать «сброс» стандартных настроек браузера для margin, padding, box-sizing, text-decoration и list-style.
Также мы задаём белый фон страницы (background-color) и шрифт (font-family) Poppins для всего текста. Вот результат, отображающий стилизованное содержимое и фон:

Стилизация шапки и логотипа

Код ниже задаёт шапке чёрный фон (background-color), серую тень (box-shadow) и нулевое смещение сверху (top). Мы фиксируем её вверху экрана с помощью липкого позиционирования (position) и делаем так, чтобы она растянулась по всей ширине устройства (width):

/* Header */
.header{
    background-color: var(--black);
    box-shadow: 1px 1px 5px 0px var(--gray);
    position: sticky;
    top: 0;
    width: 100%;
}
/* Logo */
.logo{
    display: inline-block;
    color: var(--white);
    font-size: 60px;
    margin-left: 10px;
}

Для стилизации логотипа указыаем color, font-size, and left-margin. Важно: margin — это расстояние от логотипа до других элементов, не путайте его с padding.

Теперь у нас есть красивая шапка с логотипом
Теперь у нас есть красивая шапка с логотипом

Стилизация навигационного меню

Для элемента nav мы устанавливаем свойства width и height на 100%, чтобы он занимал всю ширину экрана. Также задаём фиксированное позиционирование (position), чтобы он отображался поверх остального контента. Фон (background-color) делаем чёрным и скрываем лишний контент (overflow).
Каждому элементу меню присваивается отображение блоком (block), добавляются отступы (padding) и цвет (color). При наведении курсора мы меняем фон (background-color) с белого на серый.ХХХХХ

Наконец, с помощью свойства CSS transition, мы ставим max-height, равный нулю, чтобы меню было скрыто по умолчанию, но отображалось при щелчке по иконке:

/* Nav menu */
.nav{
    width: 100%;
    height: 100%;
    position: fixed;
    background-color: var(--black);
    overflow: hidden;

}
.menu a{
    display: block;
    padding: 30px;
    color: var(--white);
}
.menu a:hover{
    background-color: var(--gray);
}
.nav{
    max-height: 0;
    transition: max-height .5s ease-out;
}
Как сейчас выглядит меню: по умолчанию скрыто
Как сейчас выглядит меню: по умолчанию скрыто

Стилизация иконки меню

Далее мы стилизуем элемент label, чтобы он выглядел как иконка меню. Задаём cursor: pointer, отображающийся, когда пользователь взаимодействует с меню, размещаем элемент label справа и добавляем отступы.
Затем добавляем элемент span, чтобы сформировать три линии иконки меню. Для этого используются псевдо-элементы CSS [::before] и [::after], создающие верхнюю и нижнюю линии.
Селектор .hamb-line описывает центральную, или вторую, линию, а .hamb-line::before и .hamb-line::after располагают первую и третью линии на 5 пикселей выше и ниже центральной.
Наконец, мы описываем свойство display в .side-menu, чтобы скрыть чекбокс:

/* Menu Icon */
.hamb{
    cursor: pointer;
    float: right;
    padding: 40px 20px;
}/* Style label tag */

.hamb-line {
    background: var(--white);
    display: block;
    height: 2px;
    position: relative;
    width: 24px;

} /* Style span tag */

.hamb-line::before,
.hamb-line::after{
    background: var(--white);
    content: '';
    display: block;
    height: 100%;
    position: absolute;
    transition: all .2s ease-out;
    width: 100%;
}
.hamb-line::before{
    top: 5px;
}
.hamb-line::after{
    top: -5px;
}

.side-menu {
    display: none;
} /* Hide checkbox */
Показали кнопку гамбургер-меню
Показали кнопку гамбургер-меню

Стилизация нажатой иконки

В коде ниже мы указываем, как меняется иконка меню при нажатии. Для начала, когда чекбокс активен (.side-menu:checked), задаём max-height для nav, чтобы раскрыть меню.
Затем мы превращаем иконку в крестик. Сначала скрываем вторую линию, делая её фон прозрачным (background: transparent). Затем формируем Х, поворачивая верхнюю и нижнюю линии на -45 и 45 градусов соответственно.
Наконец, для улучшения пользовательского опыта на мобильных устройствах отключаем прокрутку страницы при открытом меню, чтобы фокус оставался на нём.

/* Toggle menu icon */
.side-menu:checked ~ nav{
    max-height: 100%;
}
.side-menu:checked ~ .hamb .hamb-line {
    background: transparent;
}
.side-menu:checked ~ .hamb .hamb-line::before {
    transform: rotate(-45deg);
    top:0;
}
.side-menu:checked ~ .hamb .hamb-line::after {
    transform: rotate(45deg);
    top:0;
}

body:has(.side-menu:checked) {
  overflow: hidden;
}

Вот результат, отображающий открытое меню:

Добавляем адаптивность

Чтобы меню адаптировалось к размеру экрана, мы используем media queries для условного включения свойств CSS. Иначе говоря, свойства внутри media query будут применены к веб-странице только тогда, когда набор условий действителен:

/* Responsiveness */
@media (min-width: 768px) {
    .nav{
        max-height: none;
        top: 0;
        position: relative;
        float: right;
        width: fit-content;
        background-color: transparent;
    }
    .menu li{
        float: left;
    }
    .menu a:hover{
        background-color: transparent;
        color: var(--gray);

    }

    .hamb{
        display: none;
    }
}

В коде выше мы добавляем правило @media с условием min-width: 768px. Это значит, что при ширине экрана от 768 пикселей и больше, пользователи будут видеть полноразмерное меню, а не иконку.
Для элемента nav мы убираем ограничение по высоте (max-height: none), размещая в правом верхнем углу экрана и задавая его ширину, как fit-content.
Пункты меню выравниваются в строку с помощью элемента float. Мы делаем их фон прозрачным, но серым при наведении курсора. Наконец, мы используем свойство display, чтобы скрыть иконку меню.

Оформленный сайт
Оформленный сайт

Здесь на видео можно посмотреть, как выглядит интерфейс в динамике.

Позиционирование: фиксированное, относительное или липкое

Свойство position в CSS управляет тем, как навигационное меню размещается на странице. Вместе с ним свойства top, right, bottom, left определяют позиционирование элементов.
При фиксированном позиционировании навигационное меню остаётся на месте при прокрутке. В таком случае панель навигации перекрывает контент, а содержимое страницы проходит под ним:

Относительное позиционирование размещает элемент относительно местоположения по умолчанию. Однако другой контент на странице не подстраивается под возникающий отступ:

Липкое позиционирование заставляет панель навигации прокручивается вместе с остальным содержимым, пока положение не совпадёт с указанным отступом. Остальное содержимое страницы продолжает прокручивается под меню:

Чтобы увидеть разницу, поменяйте свойство position у элемента .header с fixed на relative или sticky:

.header{
    background-color: var(--black);
    box-shadow: 1px 1px 5px 0px var(--gray);
    position: sticky;
    top: 100px;
    width: 100%;
}

Добавляем подменю

Иногда нам нужно сделать вложенные пункты меню. Это экономит место в панели навигации и делает структуру вашего сайта более организованной, и поэтому более удобной для пользователя.
Для этого в файл index.html добавляем дополнительный элемент li, как показано ниже. Иконку для класса fa fa-caret-down можно получить, добавив ссылку на файл стилей font-awesome в ваш HTML:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

...
<li class="subnav">
  <p class="subnavbtn">Contact <i class="fa fa-caret-down"></i></p>
  <div class="subnav-content">
      <a href="#">Email</a>
      <a href="#">Twitter</a>
      <a href="#">Phone</a>
  </div>
</li>

Далее в CSS можно задать правила, при которых подменю будет отображаться при наведении курсора, как показано ниже:

/* Sub nav */
.subnav-content {
    background-color:  var(--white);
    width: 100%;
    z-index: 1;
    padding: 20px 0 ;
    display: none;
  }
.subnav-content a {
    color: var(--black);
    text-decoration: none;
    padding: 0;
    margin: 10px 0;
    text-align: center;
}
.subnav:hover .subnav-content {
    display: block;
}
....
@media (min-width: 768px) {
   ....
    /* Sub nav */
    .subnav-content {
        padding: 20px 0 ;
        display: none;
        background-color:  var(--black);
    }
    .subnav-content a {
        color: white;
    }
}

В этом видео демонстрируется, как работает готовое подменю.

Дополнительная стилизация

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

CSS-переменные

CSS-переменные позволяют один раз задать значение, а затем использовать его в разных частях файла стилей. Это удобно, когда нужно быстро обновить внешний вид меню — вместо того чтобы менять одно и то же значение в нескольких местах, вы просто обновляете переменную.
Ниже пример того, как можно задать CSS-переменные и использовать их при стилизации меню:

/* Define CSS variables for colors */
:root {
    --menu-background-color: #333; /* Dark background color */
    --menu-text-color: #fff; /* White text color */
    --hover-color: #ff9900; /* Color on hover */
}

/* Use CSS variables in your menu styles */

.nav {
  width: 100%;
  height: 100%;
  background-color: var(--menu-background-color);
  overflow: hidden;
}
.menu a {
  display: block;
  padding: 30px;
  color: var(--menu-text-color);
}

Градиенты и тени

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

/* Add gradient background */
.menu {
    background-image: linear-gradient(to bottom, #333, #666); /* Gradient from dark to light */
}

/* Add box shadow */
.menu {
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); /* Shadow with blur effect */
}

Эффекты при наведении курсора

Эффекты при наведении курсора делают меню интерактивным и дают пользователю визуальную обратную связь. С их помощью можно, например, изменить цвет, размер или стиль пункта меню.
Чтобы добавить эффект к пункту меню, вы можете использовать псевдокласс :hover в CSS. Вот как это можно сделать:

/* Change text color on hover */
.menu a:hover {
    color: var(--hover-color); /* Change to your desired hover color */
}

/* Add underline on hover */
.menu a:hover {
    text-decoration: underline;
}

/* Scale effect on hover */
.menu a:hover {
    transform: scale(1.3); /* Increase the size by 30% on hover */
}

/* Fade in/out effect on hover */
.menu a {
    opacity: 0.7; /* Set initial opacity */
    transition: opacity 0.3s ease; /* Add transition for smooth effect */
}
.menu a:hover {
    opacity: 1; /* Change to full opacity on hover */
}

На GIF ниже показано, как такие эффекты работают при наведении:

Анимации

Лёгкие анимации — такие как эффект выдвижения или постепенное проявление — делают меню более живым и приятным в использовании.

Для достижения такого эффекта мы используем CSS-анимации. Сначала определим свойства в нашем CSS-файле:

/* Define the slide animation */
@keyframes slideIn {
  from {
    transform: translateY(-100%);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

/* Apply the animation to the menu items */
.side-menu:checked~nav .menu a {
  animation: slideIn 0.5s forwards;
}

В примере выше мы задали анимацию slideIn, она перемещает элементы меню сверху от -100% вниз до 0, одновременно делая их видимыми, благодаря свойству opacity. Анимация запускается при наведении курсора на пункт «Контакты» на десктопе или при открытии мобильного меню:

Доступность и ARIA-атрибуты

Доступность — важный аспект веб-разработки. Он гарантирует, что ваш сайт будет удобным для пользователей с ограниченными возможностями. Атрибуты ARIA (Accessible Rich Internet Applications) играют ключевую роль в этом.
Пример добавления ARIA-атрибутов в мобильное меню:

<!-- Navigation bar -->
  <header class="header" role="banner">
    <!-- Logo -->
    <a href="#" class="logo" aria-label="Home">
      LR
    </a>
    <!-- Hamburger icon -->
    <input class="side-menu" type="checkbox" id="side-menu" />
    <label class="hamb" for="side-menu" aria-label="Menu">
      <span class="hamb-line"></span>
    </label>
    <!-- Menu -->
    <nav class="nav" role="navigation" aria-label="Main">
      <ul class="menu">
        <li><a href="#" aria-current="page">Gallery</a></li>
        <li><a href="#">Blog</a></li>
        <li><a href="#">About</a></li>
        <!-- Contact submenu -->
        <li aria-haspopup="true">
          <div class="subnav">
            <a href="#" class="subnavbtn" aria-label="Contact" aria-controls="contact-submenu"
              tabindex="0">Contact <i class="fa fa-caret-down"></i></a>
            <ul class="subnav-content" role="menu" id="contact-submenu">
              <li><a href="#" role="menuitem">Email</a></li>
              <li><a href="#" role="menuitem">Twitter</a></li>
              <li><a href="#" role="menuitem">Phone</a></li>
            </ul>
          </div>
        </li>
      </ul>
    </nav>
  </header>

В приведённом выше коде мы добавили к шапке атрибут role="banner", который помогает программам чтения с экрана его идентифицировать. Кроме того, мы использовали role="navigation" для навигационного меню, поясняя его значение для вспомогательных технологий.
Для пользователей, использующих программы чтения с экрана, мы также добавили атрибут aria-label к логотипу и иконке. Эти метки добавляют текстовое описание, поясняющее значение этих элементов.
Атрибут aria-current="page" указывает, на какой странице находится пользователь. Это позволяет людям точно знать об их текущем местоположении на сайте.
Для подменю мы внесли изменение, используя элемент ul вместо div, чтобы вспомогательным технологиям была понятна иерархия элементов подменю, упрощая навигацию для пользователей.
Добавьте следующий CSS-код в media query:

@media (min-width: 768px) {
  ...

  .subnav-content li {
    display: block;
    width: 100%;
    background-color: var(--black);
  }
  .subnavbtn:focus+.subnav-content {
    display: block;
  }
  .subnav:hover .subnav-content {
    display: block;
  }
  .subnav:focus-within .subnav-content {
    display: block;
  }
  .subnav-content a:focus {
    background-color: var(--white);
    color: var(--black);
  }
}

Этот код улучшает отображение подменю: обеспечивается корректное расположение элементов и выделяются активные пункты подменю для пользователей, использующих только клавиатуру.
Чтобы гарантировать, что подменю остаётся видимым при фокусе на соответствующей ссылке или при наведении, мы обновили свойство display: теперь оно отображается как block при фокусе. Это изменение делает меню удобнее.
Ниже показано, как можно взаимодействовать с меню только с помощью клавиши Tab:

Горизонтальное и вертикальное меню на телефоне

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

Горизонтальное меню: плюсы и минусы

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

Вертикальное меню: плюсы и минусы

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

Горизонтальное меню
Горизонтальное меню
Вертикальное меню
Вертикальное меню

Заключение

В этом уроке мы создали отзывчивое меню по принципу mobile-first, используя только HTML и CSS — без JavaScript. Полный код, используемый в этой статье, доступен в репозитории GitHub.

Метод, используемый в этой статье, — это лишь один из многих, которые вы можете использовать. Экспериментируйте с разными способами, и выбирайте тот, что вам нравится больше.
Удачи в разработке!

Теги:
Хабы:
+4
Комментарии0

Публикации

Информация

Сайт
beget.com
Дата регистрации
Дата основания
Численность
201–500 человек
Местоположение
Россия