Веб

Как запретить горизонтальный скроллинг в мобильном меню

Решения для запрета горизонтальной прокрутки при открытии мобильного меню. CSS overflow-x hidden, body fixed position и JavaScript методы.

1 ответ 1 просмотр

Как запретить горизонтальный скроллинг страницы при открытии мобильного меню (burger-menu)? При раскрытии меню появляется белый viewport при горизонтальной прокрутке.

Запретить горизонтальный скроллинг при открытии мобильного меню можно несколькими способами с помощью CSS и JavaScript. Самые эффективные решения включают добавление класса к body с overflow-x: hidden или установку fixed position с сохранением позиции прокрутки. Это предотвратит появление белого viewport при раскрытии бургер-меню.


Содержание



Проблема горизонтального скроллинга в мобильных меню


При открытии мобильного меню (бургер-меню) часто возникает проблема, когда появляется горизонтальная прокрутка, и на экране виден белый viewport. Это происходит потому, что при раскрытии меню контент страницы сдвигается вправо, выходя за пределы ширины экрана.

Основные причины этой проблемы:

  • Контейнер меню имеет width: 100vw без учета возможного горизонтального скролла
  • CSS Grid или Flexbox элементы, которые не обтекаются правильно
  • Изображения или другие элементы, которые не ограничены max-width: 100%
  • Отсутствие сброса горизонтального скролла в body

Как отмечает Fox Scribbler, “при раскрытии бургер-меню часто появляется горизонтальная полоса прокрутки, потому что меню смещает контент вправо и выходит за пределы экрана”.


CSS решение с overflow-x: hidden


Самый простой и распространенный способ решить проблему — использовать CSS свойство overflow-x: hidden для body при открытии меню.

Базовое решение

css
/* Стили для body при открытом меню */
body.menu-open {
 overflow-x: hidden;
}

Более комплексное решение

Как рекомендует LogRocket, для полной блокировки прокрутки можно использовать:

css
body.menu-open {
 overflow-x: hidden;
 overflow-y: hidden;
 position: fixed;
 width: 100%;
}

Этот подход полностью убирает горизонтальную прокрутку, сохраняя при этом вертикальную прокрутку внутри самого меню.

Вариант с учетом padding

Если body имеет padding, чтобы предотвратить масштабирование устройства к body content-box, используйте:

css
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 с сохранением текущей позиции прокрутки.

Основной подход

javascript
// Сохраняем текущую позицию прокрутки
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 для этого подхода

css
body.menu-open {
 position: fixed;
 overflow: hidden;
 width: 100%;
}

Как объясняет CSS-Tricks, “можно установить body в fixed position как обходной путь: body.modal-open { position: fixed; overflow-y: hidden; }”.


JavaScript решения


Простой класс переключатель

javascript
const menuButton = document.querySelector('.menu-toggle');
const body = document.body;

menuButton.addEventListener('click', () => {
 body.classList.toggle('menu-open');
});

Сохранение позиции прокрутки

javascript
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 для отслеживания видимости меню:

javascript
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 при открытом меню и что все элементы внутри не создают дополнительной ширины.

css
body.menu-open {
 overflow-x: hidden !important;
}

/* Для мобильных устройств */
@media (max-width: 768px) {
 body.menu-open {
 overflow-x: hidden;
 }
}

Проблема: Меню отображается под контентом

Решение: Установите правильный z-index для меню:

css
.mobile-menu {
 z-index: 1000;
}

body.menu-open {
 overflow: hidden;
}

Проблема: Прыжок страницы при открытии/закрытии

Решение: Используйте сохранение позиции прокрутки через JavaScript:

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 платформы используйте:

css
body.tilda-menu-open {
 overflow-x: hidden !important;
 position: fixed !important;
 width: 100% !important;
}

Лучшие практики реализации


1. Тестируйте на реальных устройствах

Всегда проверяйте работу мобильного меню на реальных мобильных устройствах, а не только в эмуляторах браузера.

2. Используйте CSS переменные

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. Оптимизация производительности

javascript
// Используйте requestAnimationFrame для плавной анимации
function animateMenu() {
 requestAnimationFrame(() => {
 // Анимация меню
 });
}

4. Обработка touch событий

javascript
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. Резиновый дизайн

Убедитесь, что все элементы в меню и на странице правильно реагируют на изменение размера экрана:

css
.menu-container {
 max-width: 100%;
 overflow-x: hidden;
}

.menu-item {
 width: 100%;
 box-sizing: border-box;
}

Источники


  1. Fox Scribbler — Prevent Horizontal Scroll On Mobile — Исследование причин и решений горизонтального скроллинга при открытии мобильного меню: https://foxscribbler.com/prevent-horizontal-scroll-on-mobile/
  2. CSS-Tricks — Prevent Page Scrolling When a Modal is Open — Технические решения с fixed position и сохранением позиции прокрутки: https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/
  3. LogRocket — How to prevent overflow scrolling in CSS — Комплексный обзор причин появления горизонтального скролла и методы его предотвращения: https://blog.logrocket.com/how-to-prevent-overflow-scrolling-css/
  4. Stack Overflow — Disable horizontal scroll on mobile web — Конкретные решения для body overflow-x hidden с учетом padding: https://stackoverflow.com/questions/4192277/disable-horizontal-scroll-on-mobile-web
  5. 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
  6. 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 подходы для достижения наилучшего пользовательского опыта. Важно тестировать решение на реальных мобильных устройствах и учитывать особенности конкретной платформы или фреймворка.

Авторы
Проверено модерацией
Модерация
Как запретить горизонтальный скроллинг в мобильном меню