Блокування прокрутки сторінки
Прокрутку сторінки блокують через CSS: на <body> (або <html>) виставляють overflow: hidden, і сторінка перестає скролитися і колесом миші, і пальцем. Для повного результату цей прийом доповнюють фіксацією позиції та окремою обробкою мобільного тач-скролу.
Теорія
TL;DR
- Базовий спосіб:
document.body.style.overflow = 'hidden', зняття блокування:overflow = ''. - Акуратніше робити це CSS-класом
.no-scroll, а не інлайновими стилями. - Якщо сторінку вже було прокручено, чистий
overflow: hiddenможе смикнути контент; рятуєposition: fixedзtop: -scrollY. - Після розблокування позицію повертають через
window.scrollTo(). - На iOS Safari іноді потрібен перехоплювач
touchmoveз{ passive: false }іpreventDefault(). - Способи комбінуються: клас плюс фіксація позиції плюс мобільний запобіжник.
Швидкий приклад
function disableScroll() {
document.body.style.overflow = 'hidden';
}
function enableScroll() {
document.body.style.overflow = '';
}
openModalBtn.addEventListener('click', disableScroll);
closeModalBtn.addEventListener('click', enableScroll);Найпростіший спосіб: overflow: hidden
Браузер дозволяє заблокувати прокрутку всієї сторінки, якщо на <body> (або <html>) встановити overflow: hidden.
document.body.style.overflow = 'hidden'; // блокуємо скролЩоб повернути все назад:
document.body.style.overflow = ''; // розблоковуємоЦе найпоширеніший спосіб: сторінка залишається на місці, колесо миші і тач-скрол не працюють. У переважній більшості інтерфейсів (модалки, бургер-меню, оверлеї) цього достатньо.
Збереження позиції, щоб контент не «стрибав»
Якщо сторінка була прокручена, і ви просто ставите overflow: hidden, контент може смикнутися через зникнення смуги прокрутки.
Ось коректніший варіант із фіксацією позиції:
function disableScroll() {
const scrollY = window.scrollY;
document.body.style.position = 'fixed';
document.body.style.top = `-${scrollY}px`;
document.body.style.width = '100%';
}
function enableScroll() {
const scrollY = document.body.style.top;
document.body.style.position = '';
document.body.style.top = '';
window.scrollTo(0, parseInt(scrollY || '0') * -1);
}Тепер сторінка залишається там, де користувач зупинився, а після розблокування повертається рівно в ту саму точку. width: 100% потрібен тому, що position: fixed вириває <body> з потоку і він може стиснутися по ширині контенту.
CSS-клас замість інлайнових стилів
Зручно, якщо ви часто відкриваєте модальні вікна:
/* styles.css */
.no-scroll {
overflow: hidden;
}document.body.classList.add('no-scroll'); // заблокувати
document.body.classList.remove('no-scroll'); // розблокуватиЦе чисто, зрозуміло і легко масштабується: усі правила блокування живуть в одному місці в CSS, а JS лише перемикає клас.
Блокування скролу на мобільних пристроях
На iOS overflow: hidden іноді не допомагає при тач-скролі всередині <body>. Тоді перехоплюють подію touchmove:
function preventTouchScroll(e) {
e.preventDefault();
}
function disableScrollMobile() {
document.addEventListener('touchmove', preventTouchScroll, { passive: false });
}
function enableScrollMobile() {
document.removeEventListener('touchmove', preventTouchScroll);
}Опція { passive: false } тут обов'язкова: за замовчуванням слухачі touchmove на document вважаються пасивними, і preventDefault() у них не спрацює. Цей спосіб можна комбінувати з overflow: hidden для надійності.
Підсумкова таблиця
| Мета | Спосіб | Примітка |
|---|---|---|
| Просто заблокувати | document.body.style.overflow = 'hidden' | Підходить у переважній більшості випадків |
| Зберегти позицію | position: fixed плюс top = -scrollY | Без «стрибка» після зняття блокування |
| Часте використання | Додавання класу .no-scroll | Зручно для модалок |
| Надійність на мобільних | touchmove плюс preventDefault() | Для iOS Safari |
Запам'ятайте просто:
overflow: hiddenблокує прокрутку,position: fixedфіксує положення,touchmoveзpreventDefault()захищає від тач-скролу на мобільних.
Типові помилки
- Вішати
overflow: hiddenтільки на<html>або тільки на<body>і дивуватися, що в частині браузерів скрол лишився. Надійніше перевірити обидва елементи. - Забувати зняти блокування при закритті модалки, особливо в гілці з помилкою: сторінка назавжди лишається нерухомою.
- Використовувати
position: fixedбез збереження і подальшого відновленняscrollY: користувача викидає на початок сторінки. - Не додавати
width: 100%приposition: fixed, через що макет звужується і контент перескакує. - Реєструвати
touchmoveбез{ passive: false }: браузер проігноруєpreventDefault()і виведе попередження в консоль. - Блокувати
touchmoveна всьому документі і разом зі сторінкою вбивати скрол усередині самої модалки. Перевіряйте ціль події або вішайте слухач точково. - Рахувати блокування «глобальним прапорцем»: якщо модалок кілька, потрібен лічильник відкритих вікон, інакше закриття однієї розблокує сторінку під іншою.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.