Три рисочки, за якими ховається меню, давно стали звичною річчю: їх упізнає кожен, хто хоч раз відкривав сайт на телефоні. Колись я показував свій спосіб зробити таку кнопку на CSS з невеличкою анімацією. Тепер переробимо її як слід: справжня кнопка, яку видно програмам для незрячих і яку можна натиснути з клавіатури, а три рисочки плавно перетворюються на хрестик.
Розмітка: тільки <button>
Найпоширеніша помилка – робити бургер із посилання чи звичайного div. На вигляд різниці немає, але на div не перейдеш клавішею Tab, а посилання без адреси програми для незрячих озвучать як щось незрозуміле. Тож беремо <button>:
<button class="burger" aria-expanded="false" aria-controls="top-menu">
<span class="burger-lines"></span>
<span class="visually-hidden">Меню</span>
</button>
<nav id="top-menu" class="top-menu">
<ul>
<li><a href="/">Головна</a></li>
<li><a href="/blog">Блог</a></li>
<li><a href="/contacts">Контакти</a></li>
</ul>
</nav>
Тут кілька важливих дрібниць:
- aria-expanded каже, відкрите меню чи ні, а aria-controls – яким саме блоком керує кнопка.
- Порожній
span– це наші рисочки, а текст «Меню» в другомуspanми сховаємо з екрана, але залишимо для програм читання. Без нього кнопка буде для них просто «кнопкою» без назви.
Три рисочки на CSS
Усі три лінії малюються з одного елемента: середня – це сам span, а верхня й нижня – його псевдоелементи ::before та ::after. Розміри задаю через змінні, щоб кнопку було легко збільшити чи зменшити:
.burger {
--size: 28px;
--line: 3px;
--gap: 8px;
position: relative;
width: 44px;
height: 44px;
padding: 0;
border: 0;
background: none;
color: #222;
cursor: pointer;
}
.burger-lines,
.burger-lines::before,
.burger-lines::after {
position: absolute;
left: 50%;
width: var(--size);
height: var(--line);
margin-left: calc(var(--size) / -2);
border-radius: var(--line);
background: currentColor;
transition: transform 0.3s ease, background-color 0.3s ease;
}
.burger-lines {
top: calc(50% - var(--line) / 2);
}
.burger-lines::before,
.burger-lines::after {
content: '';
left: 0;
margin-left: 0;
}
.burger-lines::before {
transform: translateY(calc(-1 * var(--gap)));
}
.burger-lines::after {
transform: translateY(var(--gap));
}
Сама кнопка зроблена 44 на 44 пікселі, хоча рисочки менші. Це не примха: по маленькій кнопці на телефоні важко влучити пальцем, тож клікабельна площа має бути щонайменше такою. Колір рисочок береться з color кнопки через currentColor, тому для темної теми достатньо змінити один рядок.
Перетворення на хрестик
Раніше для анімації я додавав кнопці окремий клас. Але в нас уже є атрибут aria-expanded, який однаково треба перемикати, тож стилізуймо прямо за ним – так стан кнопки для очей і для програм читання ніколи не розійдеться:
.burger[aria-expanded="true"] .burger-lines {
background-color: transparent;
}
.burger[aria-expanded="true"] .burger-lines::before {
transform: rotate(45deg);
}
.burger[aria-expanded="true"] .burger-lines::after {
transform: rotate(-45deg);
}
Середня лінія стає прозорою, а верхня й нижня повертаються до центру і нахиляються в різні боки. Ось і хрестик.
Ще два штрихи, про які часто забувають:
.burger:focus-visible {
outline: 2px solid #34687d;
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
.burger-lines,
.burger-lines::before,
.burger-lines::after {
transition: none;
}
}
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
:focus-visible показує рамку навколо кнопки, коли на неї переходять клавіатурою, але не після кліку мишкою. А prefers-reduced-motion вимикає анімацію тим, хто в налаштуваннях системи попросив менше руху на екрані.
Трохи JavaScript
Скрипту лишається тільки перемикати атрибут і клас на меню:
const burger = document.querySelector('.burger');
const menu = document.getElementById('top-menu');
burger.addEventListener('click', () => {
const isOpen = burger.getAttribute('aria-expanded') !== 'true';
burger.setAttribute('aria-expanded', isOpen);
menu.classList.toggle('is-open', isOpen);
});
document.addEventListener('keydown', e => {
if (e.key === 'Escape' && burger.getAttribute('aria-expanded') === 'true') {
burger.click();
burger.focus();
}
});
Друга частина закриває меню клавішею Esc і повертає фокус на кнопку – дрібниця, але з клавіатури так користуватися меню значно приємніше. Як працює classList.toggle() з другим аргументом, я докладно розбирав у статті як змінити клас елемента в JavaScript, там же є приклад плавного розгортання самого меню.
Бургер лише на телефоні
На широкому екрані меню зазвичай видно повністю, і кнопка там не потрібна. Ховаємо її медіазапитом, а меню на телефоні показуємо лише з класом is-open:
.top-menu {
display: none;
}
.top-menu.is-open {
display: block;
}
@media (min-width: 768px) {
.burger {
display: none;
}
.top-menu {
display: block;
}
}
Що далі
Якщо тема в тебе на WordPress, кнопку з меню зручно вставити у файл header.php. Замість рисочок на CSS можна взяти готову іконку з Font Awesome, але тоді анімацію в хрестик доведеться робити заміною іконки. Поруч із бургером часто ставлять перемикач теми – ось як зробити темний режим із localStorage. А якщо хочеться меню просто з картинки, де кожна її частина веде в свій розділ, глянь, як зробити адаптивну карту зображень. На статичному сайті саме меню можна збирати автоматично – читай, як зробити меню в Eleventy.
Більше про це – за позначками CSS та Front-end розробка.
А який бургер у тебе на сайті – з рисочок на CSS, іконкою чи взагалі без нього? Пиши в коментарях 🙂


Прокоментувати
На сайті відображається лише твоє ім'я та коментар. Електронна пошта зберігається виключно для зв'язку з тобою за потреби та в жодному разі не передається стороннім особам.