← Назад к вопросам
За счет чего можно открыть бургер меню?
2.0 Middle🔥 181 комментариев
#JavaScript Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
За счет чего можно открыть бургер меню
Бургер меню — это мобильное навигационное меню (три горизонтальные линии). Его можно открыть несколькими способами, каждый с разными преимуществами.
Способ 1: Нажатие на иконку (самый популярный)
Это стандартный способ — нажимаешь на иконку, меню открывается.
import { useState } from 'react';
function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
return (
<header>
<nav>
{/* Иконка меню */}
<button
className="burger-button"
onClick={() => setIsMenuOpen(!isMenuOpen)}
aria-label="Toggle menu"
>
<span></span>
<span></span>
<span></span>
</button>
{/* Меню */}
{isMenuOpen && (
<nav className="mobile-menu">
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
)}
</nav>
</header>
);
}
CSS для анимации:
.burger-button {
display: none;
flex-direction: column;
gap: 6px;
background: none;
border: none;
cursor: pointer;
}
.burger-button span {
width: 24px;
height: 3px;
background: currentColor;
transition: all 0.3s ease;
}
/* Анимация при открытии меню */
.burger-button.active span:nth-child(1) {
transform: rotate(45deg) translateY(12px);
}
.burger-button.active span:nth-child(2) {
opacity: 0;
}
.burger-button.active span:nth-child(3) {
transform: rotate(-45deg) translateY(-12px);
}
/* Мобильное меню */
.mobile-menu {
position: fixed;
top: 60px;
left: 0;
right: 0;
background: white;
border-bottom: 1px solid #eee;
animation: slideDown 0.3s ease;
}
@keyframes slideDown {
from {
transform: translateY(-100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
/* Показывать на мобильных */
@media (max-width: 768px) {
.burger-button {
display: flex;
}
.desktop-menu {
display: none;
}
}
Способ 2: Свайп (жест на мобильном)
Открытие меню жестом с края экрана.
import { useState, useRef } from 'react';
function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const startXRef = useRef(0);
const handleTouchStart = (e: React.TouchEvent) => {
startXRef.current = e.touches[0].clientX;
};
const handleTouchEnd = (e: React.TouchEvent) => {
const endX = e.changedTouches[0].clientX;
const diffX = endX - startXRef.current;
// Свайп справа налево > 50px = открыть меню
if (diffX > 50 && startXRef.current < 50) {
setIsMenuOpen(true);
}
// Свайп слева направо > 100px = закрыть меню
if (diffX < -100 && isMenuOpen) {
setIsMenuOpen(false);
}
};
return (
<div onTouchStart={handleTouchStart} onTouchEnd={handleTouchEnd}>
{/* Контент */}
{isMenuOpen && <nav className="mobile-menu">...</nav>}
</div>
);
}
Используй библиотеку для более удобного swipe:
import { useSwipeable } from 'react-swipeable';
function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const handlers = useSwipeable({
onSwipedLeft: () => setIsMenuOpen(false),
onSwipedRight: () => setIsMenuOpen(true),
trackMouse: false,
});
return (
<div {...handlers}>
{isMenuOpen && <nav className="mobile-menu">...</nav>}
</div>
);
}
Способ 3: Ссылка в меню (desktop)
На десктопе обычное меню в header.
function Header() {
return (
<header className="header">
<nav className="desktop-menu">
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/services">Services</a>
<a href="/contact">Contact</a>
</nav>
</header>
);
}
// CSS
.desktop-menu {
display: flex;
gap: 2rem;
}
@media (max-width: 768px) {
.desktop-menu {
display: none; /* Скрыть на мобильных */
}
}
Способ 4: Overlay/Backdrop клик (закрытие)
Когда меню открыто, нажимаешь на полупрозрачный фон — меню закрывается.
function MobileMenu() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
return (
<>
{/* Backdrop (полупрозрачный фон) */}
{isMenuOpen && (
<div
className="backdrop"
onClick={() => setIsMenuOpen(false)}
role="button"
tabIndex={0}
/>
)}
{/* Меню */}
{isMenuOpen && (
<nav className="mobile-menu" onClick={(e) => e.stopPropagation()}>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
)}
</>
);
}
// CSS
.backdrop {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.mobile-menu {
position: fixed;
top: 0;
left: 0;
width: 250px; /* Ширина меню */
height: 100vh;
background: white;
z-index: 1000;
animation: slideInLeft 0.3s ease;
display: flex;
flex-direction: column;
}
@keyframes slideInLeft {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
Способ 5: Клавиатура (ESC закрыть)
Нажатие ESC закрывает меню.
import { useEffect } from 'react';
function MobileMenu() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
useEffect(() => {
const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape' && isMenuOpen) {
setIsMenuOpen(false);
}
};
document.addEventListener('keydown', handleEscape);
return () => document.removeEventListener('keydown', handleEscape);
}, [isMenuOpen]);
return (
// JSX
);
}
Способ 6: Window resize (адаптивность)
Когда меняется размер окна, меню может закрываться/открываться автоматически.
function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
useEffect(() => {
const handleResize = () => {
const nowIsMobile = window.innerWidth < 768;
setIsMobile(nowIsMobile);
// Если открыли окно на полный экран, закрыть меню
if (!nowIsMobile && isMenuOpen) {
setIsMenuOpen(false);
}
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [isMenuOpen]);
return (
<header>
{isMobile ? (
<button onClick={() => setIsMenuOpen(!isMenuOpen)}>☰</button>
) : (
<nav className="desktop-menu">...</nav>
)}
</header>
);
}
Полный пример: современное бургер меню
import { useState, useEffect } from 'react';
import './Header.css';
function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [isMobile, setIsMobile] = useState(false);
// Проверяем размер экрана
useEffect(() => {
const checkMobile = () => {
setIsMobile(window.innerWidth < 768);
if (window.innerWidth >= 768) {
setIsMenuOpen(false);
}
};
window.addEventListener('resize', checkMobile);
checkMobile();
return () => window.removeEventListener('resize', checkMobile);
}, []);
// Закрываем меню при нажатии ESC
useEffect(() => {
const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
setIsMenuOpen(false);
}
};
if (isMenuOpen) {
document.addEventListener('keydown', handleEscape);
document.body.style.overflow = 'hidden'; // Запретить скролл
}
return () => {
document.removeEventListener('keydown', handleEscape);
document.body.style.overflow = 'auto';
};
}, [isMenuOpen]);
const menuItems = [
{ label: 'Home', href: '/' },
{ label: 'About', href: '/about' },
{ label: 'Services', href: '/services' },
{ label: 'Contact', href: '/contact' },
];
return (
<header className="header">
<div className="header-content">
<div className="logo">Logo</div>
{/* Desktop меню */}
<nav className="desktop-menu">
{menuItems.map((item) => (
<a key={item.href} href={item.href}>
{item.label}
</a>
))}
</nav>
{/* Mobile burger button */}
{isMobile && (
<button
className={`burger-button ${isMenuOpen ? 'active' : ''}`}
onClick={() => setIsMenuOpen(!isMenuOpen)}
aria-label="Toggle menu"
aria-expanded={isMenuOpen}
>
<span></span>
<span></span>
<span></span>
</button>
)}
</div>
{/* Mobile меню */}
{isMobile && isMenuOpen && (
<>
{/* Backdrop */}
<div
className="backdrop"
onClick={() => setIsMenuOpen(false)}
/>
{/* Menu */}
<nav className="mobile-menu">
{menuItems.map((item) => (
<a
key={item.href}
href={item.href}
onClick={() => setIsMenuOpen(false)}
>
{item.label}
</a>
))}
</nav>
</>
)}
</header>
);
}
export default Header;
CSS:
.header {
position: relative;
background: white;
border-bottom: 1px solid #eee;
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
max-width: 1200px;
margin: 0 auto;
}
.desktop-menu {
display: flex;
gap: 2rem;
}
/* Burger button */
.burger-button {
display: none;
flex-direction: column;
gap: 6px;
background: none;
border: none;
cursor: pointer;
padding: 0;
}
.burger-button span {
width: 24px;
height: 3px;
background: currentColor;
transition: all 0.3s ease;
}
.burger-button.active span:nth-child(1) {
transform: rotate(45deg) translateY(12px);
}
.burger-button.active span:nth-child(2) {
opacity: 0;
}
.burger-button.active span:nth-child(3) {
transform: rotate(-45deg) translateY(-12px);
}
/* Mobile меню */
.backdrop {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
animation: fadeIn 0.3s ease;
}
.mobile-menu {
position: fixed;
top: 60px;
left: 0;
right: 0;
background: white;
display: flex;
flex-direction: column;
z-index: 1000;
animation: slideDown 0.3s ease;
max-height: calc(100vh - 60px);
overflow-y: auto;
}
.mobile-menu a {
padding: 1rem;
border-bottom: 1px solid #eee;
text-decoration: none;
color: inherit;
}
.mobile-menu a:active {
background: #f0f0f0;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideDown {
from {
transform: translateY(-100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
/* Мобильные */
@media (max-width: 768px) {
.burger-button {
display: flex;
}
.desktop-menu {
display: none;
}
}
Best Practices
-
Accessibility (доступность):
<button aria-label="Toggle navigation menu" aria-expanded={isMenuOpen} aria-controls="mobile-menu" > -
Performance:
- Используй CSS transitions вместо JavaScript анимаций
- Лениво рендери меню (условный рендер)
- Дебаунс resize события
-
UX:
- Закрывай меню при клике на ссылку
- Поддерживай ESC для закрытия
- Запретри скролл body при открытом меню
- Используй плавные анимации
Вывод
Бургер меню можно открыть за счет:
- Клик на иконку — основной способ
- Свайп — для удобства на мобильных
- Desktop меню — обычные ссылки
- Backdrop клик — закрытие
- ESC клавиша — улучшение UX
- Window resize — адаптивность
Современное меню должно поддерживать все эти способы для лучшей UX!