Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Как сделать меню-гамбургер без JavaScript

Короткий ответ

Скрытый флажок хранит состояние «открыто», label им управляет, а :has() показывает меню:

<style>
  .nav { padding: 8px; background: navy; color: white; }
  .nav input { position: absolute; opacity: 0; }
  .nav label { cursor: pointer; font-size: 24px; }
  .nav input:focus-visible + label { outline: 2px solid orange; }
  .nav .links { display: none; flex-direction: column; gap: 6px; padding-top: 8px; }
  .nav:has(input:checked) .links { display: flex; }
  .nav a { color: white; }
</style>
 
<nav class="nav">
  <input type="checkbox" id="burger" aria-label="Menu"><label for="burger">☰</label>
  <div class="links"><a href="https://example.com">Home</a><a href="https://example.com">Shop</a><a href="https://example.com">About</a></div>
</nav>

Только на телефоне

На широком экране кнопка не нужна — меню показывают всегда:

@media (min-width: 700px) {
  .nav label { display: none; }
  .nav .links { display: flex; flex-direction: row; }
}

Вариант с popover

Атрибут popover даёт меню поверх страницы, закрытие по Esc и клику снаружи, а кнопка с popovertarget сообщает экранным дикторам, открыто меню или нет:

<button popovertarget="side" aria-label="Menu">☰</button>
<nav id="side" popover style="margin: 0; height: 100%; padding: 16px;"><a href="https://example.com">Home</a><br><a href="https://example.com">Shop</a></nav>

Частая ошибка

Прячут флажок через display: none: тогда меню не открыть с клавиатуры. Скрывайте его визуально, как в первом примере, и дайте ему aria-label, ведь значок «☰» ничего не скажет экранному диктору.

Функции из этого ответа

  • <input type="checkbox"> — Флажок (`checkbox`) — независимый выбор «да/нет»; переключатель (`radio`) — один вариант из группы.
  • :has() — Выбирает элемент, внутри которого есть что-то подходящее под селектор в скобках, — «селектор родителя».
  • :checked — Срабатывает у отмеченного флажка или переключателя и у выбранного `<option>`.
  • <label> — Подпись к полю формы.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.