- Почему без JavaScript?
- Простое одноуровневое адаптивное меню на чистом CSS
- HTML разметка меню
- CSS оформление меню
- Продвинутое адаптивное меню на чистом CSS
- Сравнение со старой версией
- HTML разметка
- Базовая структура (1 уровень)
- Добавляем Dropdown подменю
- Как это работает:
- Многоуровневый Dropdown (3 уровня)
- CSS стили — пошагово
- Шаг 1: CSS переменные и reset
- Шаг 2: Header и контейнер
- Шаг 3: Скрываем checkbox и готовим гамбургер
- Шаг 4: Основное меню (desktop)
- Шаг 5: Dropdown подменю (desktop)
- Шаг 6: Мобильная версия (max-width: 768px)
- Полный рабочий код
- Как настроить под себя
- Изменить цвета
- Изменить точку перехода (breakpoint)
- Добавить больше пунктов
- Тестирование и отладка
- Проверка в разных браузерах
- Проверка на устройствах
- Валидация HTML
- Улучшения для продакшена
- Добавить ARIA атрибуты для accessibility
- Оптимизировать для старых браузеров
- Добавить активный пункт меню
- Минифицировать CSS
- Заключение
- Что дальше?
В данном уроке я расскажу о том как на чистом CSS (без использования JS) сверстать горизонтальное адаптивное (складывающегося) — которое можно установить на любой сайт. Это сейчас очень актуально — так как пришла эра быстрых сайтов, скоро походу фейерверки типа бутстрапа будут не в моде — для тех кто хочет хороших позиций в гугле.
Сделаем 2 версии:
- Простое одноуровневое с поддержкой IE 11 (если он еще кому то нужен).
- Продвинутое многоуровневое, на современных технологиях так сказать.
Почему без JavaScript?
JavaScript — мощный инструмент, но для простого меню он не всегда нужен. Вот почему CSS-only решение лучше:
- Быстрее загрузка — нет JS файлов для загрузки и парсинга;
- SEO friendly — поисковики видят меню сразу, без ожидания JS;
- Accessibility — работает даже если JS отключен (1-2% пользователей);
- Экономия батареи — CSS анимации аппаратно ускорены;
- Безопасность — нет риска XSS атак через JS;
- Проще поддержка — один язык вместо двух.
JavaScript стоит добавлять когда нужны:
- Сложные мега-меню с асинхронной загрузкой данных;
- Sticky header с плавным появлением при прокрутке;
- Поиск по меню в реальном времени;
- Интеграция с аналитикой (отслеживание кликов);
- Динамическое изменение меню в зависимости от роли пользователя.
Для обычного меню и меню с dropdown — CSS вполне достаточно!
Простое одноуровневое адаптивное меню на чистом CSS
HTML разметка меню
<header>
<div class="container">
<a href="#" id="logo" target="_blank">web-revenue.ru</a>
<label for="toggle-1" class="toggle-menu"><i class="toggle-icon"></i></label>
<input type="checkbox" id="toggle-1">
<nav>
<ul>
<li><a href="#logo">Главная</a></li>
<li><a href="#about">О компании</a></li>
<li><a href="#portfolio">Портфолио</a></li>
<li><a href="#services">Услуги</a></li>
<li><a href="#gallery">Галерея</a></li>
<li><a href="#contact">Контакты</a></li>
</ul>
</nav>
</div>
</header>
Здесь все при дельно просто — за основу взять стандартные HTML элементы
CSS оформление меню
Сначала зададим стили основным элементам
body{margin:0;overflow-x:hidden}
header{width:100%;display:table;background-color:#002e5b;margin-bottom:50px}
.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}
.toggle-icon{background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");width:30px;
height:30px;position:absolute;}
@media (min-width: 1200px) {
.container{max-width:1140px}
}
#logo{float:left;font-size:25px;text-transform:uppercase;color:#fffab2;font-weight:600;text-decoration:none;padding:11px 0}
nav{width:auto;float:right;margin-top:7px}
nav ul{display:table;float:right;margin:0;padding:0}
nav ul li{float:left;list-style-type:none}
nav ul li:last-child{padding-right:0}
nav ul li a{color:#e4f2ff;font-size:19px;padding:7px 19px;display:inline-block;text-decoration:none}
nav ul li a:hover{background-color:#143a06;color:#fff9c8;text-decoration:underline}
input[type=checkbox],label{display:none}
И добавляем адаптивность.
@media only screen and (max-width: 980px) {
header{padding:20px 0}
#logo{padding:0}
input[type=checkbox]{position:absolute;top:-9999px;left:-9999px;background:none}
input[type=checkbox]:fous{background:none}
label{float:right;display:inline-block;cursor:pointer;margin-right:65px}
input[type=checkbox]:checked ~ nav{display:block}
nav{display:none;position:absolute;right:0;top:50px;background-color:#002e5b;padding:0;z-index:99}
nav ul{width:auto}
nav ul li{float:none;padding:0;width:100%;display:table}
nav ul li a{color:#FFF;font-size:15px;padding:10px 20px;display:block;border-bottom:1px solid rgba(225,225,225,0.1)}
}
@media only screen and (max-width: 360px) {
label{padding:5px 0}
#logo{font-size:20px}
nav{top:47px}
}
В принципе все, вам нужно только подправить мелкие нюансы под себя и все — легкое адаптивное меню без js готово.
Продвинутое адаптивное меню на чистом CSS
С dropdown подменю, без JavaScript — улучшенная версия 2026.
Что нового в этой версии:
- Dropdown подменю — работает на desktop через :hover, на мобиле через checkbox;
- CSS переменные — легко меняйте цвета в одном месте;
- Плавные анимации — современные transition и transform;
- Улучшенная мобильная версия — overlay фон, плавное открытие;
- Иконки через SVG — не нужны внешние шрифты;
- Валидный HTML5 — проверено W3C валидатором;
- Accessibility — работает с клавиатуры;
- Меньше кода — оптимизировано и убрано лишнее.
Сравнение со старой версией
| Функция | Старая версия | Новая версия ✨ |
|---|---|---|
| Dropdown меню | ❌ Нет | ✅ Есть (многоуровневое) |
| CSS переменные | ❌ Нет | ✅ Да (легко менять цвета) |
| Анимации | Базовые | Плавные transform + transition |
| Overlay фон | ❌ Нет | ✅ Затемнение с blur |
| Иконки | SVG inline | SVG data-uri (чище) |
| Размер кода | ~150 строк | ~200 строк (но больше функций) |
| JavaScript | 0 строк ✅ | 0 строк ✅ |
HTML разметка
Структура меню семантическая и валидная по HTML5. Используем <nav>, <ul>, <li>.
Базовая структура (1 уровень)
<header class="header">
<div class="container">
<!-- Логотип -->
<a href="#" class="logo">Web Revenue</a>
<!-- Checkbox для мобильного меню (скрыт) -->
<input type="checkbox" id="menu-toggle" class="menu-toggle">
<!-- Label = кнопка гамбургера -->
<label for="menu-toggle" class="menu-icon">
<span class="menu-icon-line"></span>
</label>
<!-- Навигация -->
<nav class="nav">
<ul class="menu">
<li><a href="#home">Главная</a></li>
<li><a href="#about">О компании</a></li>
<li><a href="#services">Услуги</a></li>
<li><a href="#portfolio">Портфолио</a></li>
<li><a href="#contact">Контакты</a></li>
</ul>
</nav>
</div>
</header>
Добавляем Dropdown подменю
Для dropdown используем вложенный <ul> внутри <li>. На desktop работает через :hover, на мобиле — через дополнительный checkbox.
<li class="dropdown">
<!-- Checkbox для открытия dropdown на мобиле -->
<input type="checkbox" id="dropdown-services" class="dropdown-toggle">
<!-- Label = клик по ссылке на мобиле -->
<label for="dropdown-services" class="dropdown-label">
<a href="#services">Услуги</a>
<span class="dropdown-arrow">▾</span>
</label>
<!-- Подменю -->
<ul class="submenu">
<li><a href="#web-dev">Веб-разработка</a></li>
<li><a href="#seo">SEO продвижение</a></li>
<li><a href="#design">Дизайн</a></li>
<li><a href="#support">Поддержка сайтов</a></li>
</ul>
</li>
Как это работает:
- Desktop (hover): При наведении на
.dropdownпоявляется.submenuчерез CSS:hover; - Mobile (checkbox): При клике на label активируется checkbox, CSS видит
:checkedи показывает подменю; - Стрелка
▾поворачивается при открытии черезtransform: rotate(180deg).
Трюк с Checkbox.
Checkbox — единственный HTML элемент, который может хранить состояние (checked/unchecked) без JavaScript. Мы его скрываем через
display: none, а управляем через<label>.Когда пользователь кликает на label, checkbox меняет состояние. CSS видит это через селектор
:checkedи показывает/скрывает нужные элементы!
Многоуровневый Dropdown (3 уровня)
Можно вложить dropdown внутри dropdown. Просто повторяем структуру:
<li class="dropdown">
<input type="checkbox" id="dropdown-marketing" class="dropdown-toggle">
<label for="dropdown-marketing" class="dropdown-label">
<a href="#marketing">Маркетинг</a>
<span class="dropdown-arrow">▾</span>
</label>
<ul class="submenu">
<li><a href="#contextual">Контекстная реклама</a></li>
<!-- Вложенный dropdown (3-й уровень) -->
<li class="dropdown">
<input type="checkbox" id="dropdown-smm" class="dropdown-toggle">
<label for="dropdown-smm" class="dropdown-label">
<a href="#smm">SMM</a>
<span class="dropdown-arrow">›</span>
</label>
<ul class="submenu">
<li><a href="#vk">ВКонтакте</a></li>
<li><a href="#telegram">Telegram</a></li>
<li><a href="#instagram">Instagram*</a></li>
</ul>
</li>
<li><a href="#email">Email рассылки</a></li>
</ul>
</li>
CSS стили — пошагово
Шаг 1: CSS переменные и reset
:root {
/* Цвета */
--primary-color: #002e5b;
--primary-hover: #004080;
--text-color: #ffffff;
--text-hover: #fffab2;
--dropdown-bg: #ffffff;
--dropdown-text: #333333;
--overlay-bg: rgba(0, 0, 0, 0.7);
/* Размеры */
--header-height: 70px;
--container-width: 1200px;
/* Анимация */
--transition-speed: 0.3s;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
line-height: 1.6;
color: #333;
}
a {
text-decoration: none;
color: inherit;
transition: color var(--transition-speed);
}
ul {
list-style: none;
}
Зачем CSS переменные?
Представьте что вам нужно изменить основной цвет меню с синего на зеленый. Без переменных пришлось бы менять в 20+ местах. С переменными — меняете одну строку
--primary-color: #002e5b;и всё!
Шаг 2: Header и контейнер
.header {
background-color: var(--primary-color);
position: sticky;
top: 0;
z-index: 1000;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.container {
max-width: var(--container-width);
margin: 0 auto;
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
height: var(--header-height);
}
.logo {
font-size: 24px;
font-weight: 700;
color: var(--text-color);
text-transform: uppercase;
letter-spacing: 1px;
transition: color var(--transition-speed);
}
.logo:hover {
color: var(--text-hover);
}
Шаг 3: Скрываем checkbox и готовим гамбургер
/* Скрываем все checkbox */
.menu-toggle,
.dropdown-toggle {
display: none;
}
/* Гамбургер иконка */
.menu-icon {
display: none;
cursor: pointer;
width: 30px;
height: 30px;
position: relative;
z-index: 1001;
}
.menu-icon-line,
.menu-icon-line::before,
.menu-icon-line::after {
display: block;
width: 100%;
height: 3px;
background: var(--text-color);
border-radius: 3px;
transition: all var(--transition-speed);
}
.menu-icon-line {
position: relative;
top: 50%;
transform: translateY(-50%);
}
.menu-icon-line::before,
.menu-icon-line::after {
content: '';
position: absolute;
left: 0;
}
.menu-icon-line::before {
top: -8px;
}
.menu-icon-line::after {
top: 8px;
}
/* Анимация в крестик при открытии */
.menu-toggle:checked ~ .menu-icon .menu-icon-line {
background: transparent;
}
.menu-toggle:checked ~ .menu-icon .menu-icon-line::before {
top: 0;
transform: rotate(45deg);
}
.menu-toggle:checked ~ .menu-icon .menu-icon-line::after {
top: 0;
transform: rotate(-45deg);
}
Шаг 4: Основное меню (desktop)
.menu {
display: flex;
align-items: center;
gap: 5px;
}
.menu > li {
position: relative;
}
.menu > li > a,
.dropdown-label {
display: flex;
align-items: center;
padding: 10px 18px;
color: var(--text-color);
font-size: 16px;
font-weight: 500;
border-radius: 6px;
transition: all var(--transition-speed);
cursor: pointer;
}
.menu > li > a:hover,
.menu > li:hover .dropdown-label {
background-color: var(--primary-hover);
color: var(--text-hover);
}
/* Стрелка dropdown */
.dropdown-arrow {
margin-left: 5px;
font-size: 12px;
transition: transform var(--transition-speed);
}
Шаг 5: Dropdown подменю (desktop)
/* Подменю скрыто по умолчанию */
.submenu {
position: absolute;
top: 100%;
left: 0;
min-width: 220px;
background: var(--dropdown-bg);
border-radius: 8px;
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.15);
padding: 8px 0;
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: all var(--transition-speed);
z-index: 100;
}
/* Показываем при hover на родителя */
.dropdown:hover > .submenu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
/* Поворачиваем стрелку */
.dropdown:hover .dropdown-arrow {
transform: rotate(180deg);
}
/* Стили ссылок в подменю */
.submenu li a {
display: block;
padding: 10px 20px;
color: var(--dropdown-text);
font-size: 15px;
transition: all var(--transition-speed);
}
.submenu li a:hover {
background-color: rgba(65, 84, 241, 0.1);
color: var(--primary-color);
padding-left: 25px;
}
/* Вложенный dropdown (3-й уровень) открывается справа */
.submenu .dropdown .submenu {
top: 0;
left: 100%;
margin-left: 5px;
}
.submenu .dropdown:hover .dropdown-arrow {
transform: rotate(-90deg);
}
Шаг 6: Мобильная версия (max-width: 768px)
@media (max-width: 768px) {
/* Показываем гамбургер */
.menu-icon {
display: block;
}
/* Скрываем меню по умолчанию */
.nav {
position: fixed;
top: 0;
right: -100%;
width: 300px;
height: 100vh;
background: var(--primary-color);
padding: 80px 0 20px;
overflow-y: auto;
transition: right var(--transition-speed);
z-index: 999;
}
/* Показываем при checked */
.menu-toggle:checked ~ .nav {
right: 0;
}
/* Overlay фон */
.menu-toggle:checked ~ .nav::before {
content: '';
position: fixed;
top: 0;
left: 0;
right: 300px;
bottom: 0;
background: var(--overlay-bg);
backdrop-filter: blur(3px);
z-index: -1;
}
/* Меню вертикальное */
.menu {
flex-direction: column;
align-items: stretch;
gap: 0;
}
.menu > li {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.menu > li > a,
.dropdown-label {
padding: 15px 20px;
justify-content: space-between;
}
/* Dropdown на мобиле */
.submenu {
position: static;
background: rgba(0, 0, 0, 0.2);
box-shadow: none;
border-radius: 0;
max-height: 0;
overflow: hidden;
opacity: 1;
visibility: visible;
transform: none;
transition: max-height var(--transition-speed);
}
/* Открываем через checkbox */
.dropdown-toggle:checked ~ .submenu {
max-height: 500px;
}
.dropdown-toggle:checked ~ .dropdown-label .dropdown-arrow {
transform: rotate(180deg);
}
/* Вложенные dropdown на мобиле */
.submenu .submenu {
background: rgba(0, 0, 0, 0.3);
margin-left: 0;
}
.submenu li a {
padding: 12px 20px 12px 40px;
color: var(--text-color);
}
.submenu .submenu li a {
padding-left: 60px;
}
}
Полный рабочий код
Собираем всё вместе в один HTML файл, готовый к использованию:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Адаптивное меню с dropdown на чистом CSS</title>
<style>
/* Вставьте весь CSS отсюда */
</style>
</head>
<body>
<header class="header">
<div class="container">
<a href="#" class="logo">Web Revenue</a>
<input type="checkbox" id="menu-toggle" class="menu-toggle">
<label for="menu-toggle" class="menu-icon">
<span class="menu-icon-line"></span>
</label>
<nav class="nav">
<ul class="menu">
<li><a href="#">Главная</a></li>
<li><a href="#">О компании</a></li>
<!-- Dropdown -->
<li class="dropdown">
<input type="checkbox" id="dropdown-services" class="dropdown-toggle">
<label for="dropdown-services" class="dropdown-label">
<span>Услуги</span>
<span class="dropdown-arrow">▾</span>
</label>
<ul class="submenu">
<li><a href="#">Веб-разработка</a></li>
<li><a href="#">SEO продвижение</a></li>
<li><a href="#">Дизайн</a></li>
</ul>
</li>
<li><a href="#">Портфолио</a></li>
<li><a href="#">Контакты</a></li>
</ul>
</nav>
</div>
</header>
<!-- Ваш контент -->
<main style="padding: 40px 20px;">
<div class="container">
<h1>Добро пожаловать!</h1>
<p>Это адаптивное меню на чистом CSS.</p>
</div>
</main>
</body>
</html>
Как настроить под себя
Изменить цвета
Откройте секцию :root и поменяйте переменные:
:root {
--primary-color: #002e5b; /* Фон header */
--primary-hover: #004080; /* Фон при hover */
--text-color: #ffffff; /* Цвет текста */
--text-hover: #fffab2; /* Цвет текста при hover */
--dropdown-bg: #ffffff; /* Фон dropdown */
--dropdown-text: #333333; /* Текст в dropdown */
}
Изменить точку перехода (breakpoint)
По умолчанию мобильная версия включается на экранах меньше 768px. Чтобы изменить:
/* Было */
@media (max-width: 768px) { ... }
/* Стало (например 992px) */
@media (max-width: 992px) { ... }
Добавить больше пунктов
Просто скопируйте структуру <li> и измените текст и ссылки:
<li><a href="#pricing">Цены</a></li>
<li><a href="#faq">FAQ</a></li>
<li><a href="#blog">Блог</a></li>
Вывод: Когда использовать CSS-only меню?
Используйте CSS-only если:
- Нужно простое меню с 1-2 уровнями dropdown;
- Важна скорость загрузки и SEO;
- Сайт статический или на простом CMS;
- Хотите минимальные зависимости.
Добавьте JavaScript если:
- Нужны сложные мега-меню с категориями;
- Требуется интеграция с аналитикой;
- Нужен sticky header с плавным появлением;
- Нужна полная accessibility поддержка.
Тестирование и отладка
Проверка в разных браузерах
Меню протестировано в:
- ✅ Chrome 120+ (Windows, macOS, Android)
- ✅ Firefox 121+ (Windows, macOS)
- ✅ Safari 17+ (macOS, iOS)
- ✅ Edge 120+ (Windows)
- ✅ Opera 106+
- ⚠️ IE11 — не поддерживает CSS переменные (нужны fallback значения)
Проверка на устройствах
- Откройте страницу в браузере;
- Нажмите F12 → DevTools;
- Нажмите Ctrl+Shift+M → режим устройств;
- Выберите разные устройства из списка;
- Проверьте что:
- На desktop dropdown открывается при hover;
- На мобиле гамбургер открывает меню;
- Dropdown на мобиле открывается по клику;
- Overlay фон затемняет страницу.
Валидация HTML
Проверьте код в W3C валидаторе:
- Откройте https://validator.w3.org/
- Выберите «Validate by Direct Input»
- Вставьте ваш HTML код
- Нажмите «Check»
✅ Код должен быть валидным без ошибок!
Улучшения для продакшена
Добавить ARIA атрибуты для accessibility
<nav class="nav" role="navigation" aria-label="Основное меню">
<ul class="menu">
<li class="dropdown">
<input type="checkbox" id="dropdown-services"
class="dropdown-toggle"
aria-expanded="false">
<label for="dropdown-services"
class="dropdown-label"
role="button"
aria-haspopup="true">
<span>Услуги</span>
<span class="dropdown-arrow" aria-hidden="true">▾</span>
</label>
<ul class="submenu" role="menu">
<li role="none"><a href="#" role="menuitem">Веб-разработка</a></li>
</ul>
</li>
</ul>
</nav>
Оптимизировать для старых браузеров
Если нужна поддержка IE11, добавьте fallback для CSS переменных:
.header {
background-color: #002e5b; /* Fallback */
background-color: var(--primary-color); /* Современные браузеры */
}
Добавить активный пункт меню
/* Подсвечиваем активную страницу */
.menu li a.active {
background-color: var(--primary-hover);
color: var(--text-hover);
font-weight: 600;
}
/* В HTML */
<li><a href="#" class="active">Главная</a></li>
Минифицировать CSS
Перед публикацией сожмите CSS через онлайн-инструмент:
Размер уменьшится с ~8kb до ~5kb (~38% меньше).
Заключение
Вы создали современное адаптивное меню с dropdown на чистом CSS! Оно:
- Работает на всех устройствах;
- Имеет dropdown подменю (до 3 уровней);
- Не требует JavaScript;
- Быстро загружается;
- SEO friendly;
- Легко настраивается через CSS переменные;
- Валидный HTML5;
- Работает в 99% браузеров.
Что дальше?
Если вам нужно более продвинутое меню с JavaScript, sticky header, мега-меню и Intersection Observer API, читайте следующий урок: Современное Mobile-first меню для сайта с dropdown, mega menu, sticky header.










Все классно, но не предусмотрены подпункты.
Для этого лучше использовать JS
Добрый день! Подскажите пожалуйста, как сместить лейбл влево почти до конца и соответственно меню вправо также почти до конца?
Если правильно понял вопрос, то ширина контейнера задается классом
.containerкоторый ограничивает ширину в1140px, нужно больше поправьте CSS:@media (min-width: 1200px) {.container{max-width:1140px}
}
Отличное меню
Но никак не вяжется с валидатором html
может возможно label заменить чем-то?
Здравствуйте. Поменял вывод кнопки бургера и css немного изменил, теперь html валиден http://prntscr.com/10g4je8 (при условии, что css выносите в отдельный файл). Статья обновлена, смотрите.