Как запретить горизонтальный скроллинг в мобильном меню
Решения для запрета горизонтальной прокрутки при открытии мобильного меню. CSS overflow-x hidden, body fixed position и JavaScript методы.
Как запретить горизонтальный скроллинг страницы при открытии мобильного меню (burger-menu)? При раскрытии меню появляется белый viewport при горизонтальной прокрутке.
Запретить горизонтальный скроллинг при открытии мобильного меню можно несколькими способами с помощью CSS и JavaScript. Самые эффективные решения включают добавление класса к body с overflow-x: hidden или установку fixed position с сохранением позиции прокрутки. Это предотвратит появление белого viewport при раскрытии бургер-меню.
Содержание
- Проблема горизонтального скроллинга в мобильных меню
- CSS решение с overflow-x: hidden
- Fixed position для body
- JavaScript решения
- Типичные проблемы и их решения
- Лучшие практики реализации
Проблема горизонтального скроллинга в мобильных меню
При открытии мобильного меню (бургер-меню) часто возникает проблема, когда появляется горизонтальная прокрутка, и на экране виден белый viewport. Это происходит потому, что при раскрытии меню контент страницы сдвигается вправо, выходя за пределы ширины экрана.
Основные причины этой проблемы:
- Контейнер меню имеет
width: 100vwбез учета возможного горизонтального скролла - CSS Grid или Flexbox элементы, которые не обтекаются правильно
- Изображения или другие элементы, которые не ограничены
max-width: 100% - Отсутствие сброса горизонтального скролла в body
Как отмечает Fox Scribbler, “при раскрытии бургер-меню часто появляется горизонтальная полоса прокрутки, потому что меню смещает контент вправо и выходит за пределы экрана”.
CSS решение с overflow-x: hidden
Самый простой и распространенный способ решить проблему — использовать CSS свойство overflow-x: hidden для body при открытии меню.
Базовое решение
/* Стили для body при открытом меню */
body.menu-open {
overflow-x: hidden;
}
Более комплексное решение
Как рекомендует LogRocket, для полной блокировки прокрутки можно использовать:
body.menu-open {
overflow-x: hidden;
overflow-y: hidden;
position: fixed;
width: 100%;
}
Этот подход полностью убирает горизонтальную прокрутку, сохраняя при этом вертикальную прокрутку внутри самого меню.
Вариант с учетом padding
Если body имеет padding, чтобы предотвратить масштабирование устройства к body content-box, используйте:
body {
overflow-x: hidden;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body.menu-open {
overflow-x: hidden;
position: fixed;
width: 100%;
}
Fixed position для body
Еще один эффективный метод — использование fixed position для body с сохранением текущей позиции прокрутки.
Основной подход
// Сохраняем текущую позицию прокрутки
const scrollY = window.scrollY;
// При открытии меню
document.body.style.position = 'fixed';
document.body.style.top = `-${scrollY}px`;
document.body.style.width = '100%';
document.body.style.overflow = 'hidden';
// При закрытии меню
document.body.style.position = '';
document.body.style.top = '';
document.body.style.width = '';
document.body.style.overflow = '';
window.scrollTo(0, scrollY);
CSS для этого подхода
body.menu-open {
position: fixed;
overflow: hidden;
width: 100%;
}
Как объясняет CSS-Tricks, “можно установить body в fixed position как обходной путь: body.modal-open { position: fixed; overflow-y: hidden; }”.
JavaScript решения
Простой класс переключатель
const menuButton = document.querySelector('.menu-toggle');
const body = document.body;
menuButton.addEventListener('click', () => {
body.classList.toggle('menu-open');
});
Сохранение позиции прокрутки
let scrollPosition = 0;
function openMenu() {
scrollPosition = window.pageYOffset;
document.body.style.overflow = 'hidden';
document.body.style.position = 'fixed';
document.body.style.top = `-${scrollPosition}px`;
document.body.style.width = '100%';
}
function closeMenu() {
document.body.style.overflow = '';
document.body.style.position = '';
document.body.style.top = '';
document.body.style.width = '';
window.scrollTo(0, scrollPosition);
}
Решение с использованием Intersection Observer
Для сложных случаев можно использовать Intersection Observer для отслеживания видимости меню:
const menu = document.querySelector('.mobile-menu');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
document.body.classList.add('menu-open');
} else {
document.body.classList.remove('menu-open');
}
});
}, { threshold: 0.1 });
observer.observe(menu);
Типичные проблемы и их решения
Проблема: Белый viewport при прокрутке
Решение: Убедитесь, что body имеет overflow-x: hidden при открытом меню и что все элементы внутри не создают дополнительной ширины.
body.menu-open {
overflow-x: hidden !important;
}
/* Для мобильных устройств */
@media (max-width: 768px) {
body.menu-open {
overflow-x: hidden;
}
}
Проблема: Меню отображается под контентом
Решение: Установите правильный z-index для меню:
.mobile-menu {
z-index: 1000;
}
body.menu-open {
overflow: hidden;
}
Проблема: Прыжок страницы при открытии/закрытии
Решение: Используйте сохранение позиции прокрутки через JavaScript:
const scrollY = window.scrollY;
// Открытие
document.body.style.position = 'fixed';
document.body.style.top = `-${scrollY}px`;
// Закрытие
document.body.style.position = '';
document.body.style.top = '';
window.scrollTo(0, scrollY);
Проблема: Мобильное меню тильда
Для Tilda платформы используйте:
body.tilda-menu-open {
overflow-x: hidden !important;
position: fixed !important;
width: 100% !important;
}
Лучшие практики реализации
1. Тестируйте на реальных устройствах
Всегда проверяйте работу мобильного меню на реальных мобильных устройствах, а не только в эмуляторах браузера.
2. Используйте CSS переменные
:root {
--menu-width: 280px;
}
body.menu-open {
overflow-x: hidden;
}
.mobile-menu {
transform: translateX(0);
transition: transform 0.3s ease;
}
body:not(.menu-open) .mobile-menu {
transform: translateX(-100%);
}
3. Оптимизация производительности
// Используйте requestAnimationFrame для плавной анимации
function animateMenu() {
requestAnimationFrame(() => {
// Анимация меню
});
}
4. Обработка touch событий
let touchStartX = 0;
let touchEndX = 0;
document.addEventListener('touchstart', e => {
touchStartX = e.changedTouches[0].screenX;
});
document.addEventListener('touchend', e => {
touchEndX = e.changedTouches[0].screenX;
handleSwipe();
});
function handleSwipe() {
if (touchEndX < touchStartX - 50) {
// Свайп влево - открыть меню
openMenu();
}
if (touchEndX > touchStartX + 50) {
// Свайп вправо - закрыть меню
closeMenu();
}
}
5. Резиновый дизайн
Убедитесь, что все элементы в меню и на странице правильно реагируют на изменение размера экрана:
.menu-container {
max-width: 100%;
overflow-x: hidden;
}
.menu-item {
width: 100%;
box-sizing: border-box;
}
Источники
- Fox Scribbler — Prevent Horizontal Scroll On Mobile — Исследование причин и решений горизонтального скроллинга при открытии мобильного меню: https://foxscribbler.com/prevent-horizontal-scroll-on-mobile/
- CSS-Tricks — Prevent Page Scrolling When a Modal is Open — Технические решения с fixed position и сохранением позиции прокрутки: https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/
- LogRocket — How to prevent overflow scrolling in CSS — Комплексный обзор причин появления горизонтального скролла и методы его предотвращения: https://blog.logrocket.com/how-to-prevent-overflow-scrolling-css/
- Stack Overflow — Disable horizontal scroll on mobile web — Конкретные решения для body overflow-x hidden с учетом padding: https://stackoverflow.com/questions/4192277/disable-horizontal-scroll-on-mobile-web
- Stack Overflow — Horizontal Scroll when Navigation menu translates webpage — Решение с использованием translateX и overflow-x hidden: https://stackoverflow.com/questions/61922346/horizontal-scroll-when-navigation-menu-translates-webpage-with-overflow-hidden
- Stack Overflow — CSS overflow-x issue for Off-Canvas menu — Пример кода с классом body.opened и overflow управлением: https://stackoverflow.com/questions/18316319/css-overflow-x-issue-for-off-canvas-menu
Заключение
Запретить горизонтальный скроллинг при открытии мобильного меню можно несколькими проверенными методами. Наиболее эффективным решением является добавление класса к body с overflow-x: hidden или использование fixed position с сохранением текущей позиции прокрутки. Для сложных случаев можно комбинировать CSS и JavaScript подходы для достижения наилучшего пользовательского опыта. Важно тестировать решение на реальных мобильных устройствах и учитывать особенности конкретной платформы или фреймворка.