Skip to main content

Блокування прокрутки сторінки

Прокрутку сторінки блокують через 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().
  • Способи комбінуються: клас плюс фіксація позиції плюс мобільний запобіжник.

Швидкий приклад

javascript
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.

javascript
document.body.style.overflow = 'hidden'; // блокуємо скрол

Щоб повернути все назад:

javascript
document.body.style.overflow = ''; // розблоковуємо

Це найпоширеніший спосіб: сторінка залишається на місці, колесо миші і тач-скрол не працюють. У переважній більшості інтерфейсів (модалки, бургер-меню, оверлеї) цього достатньо.

Збереження позиції, щоб контент не «стрибав»

Якщо сторінка була прокручена, і ви просто ставите overflow: hidden, контент може смикнутися через зникнення смуги прокрутки.

Ось коректніший варіант із фіксацією позиції:

javascript
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-клас замість інлайнових стилів

Зручно, якщо ви часто відкриваєте модальні вікна:

css
/* styles.css */ .no-scroll { overflow: hidden; }
javascript
document.body.classList.add('no-scroll'); // заблокувати document.body.classList.remove('no-scroll'); // розблокувати

Це чисто, зрозуміло і легко масштабується: усі правила блокування живуть в одному місці в CSS, а JS лише перемикає клас.

Блокування скролу на мобільних пристроях

На iOS overflow: hidden іноді не допомагає при тач-скролі всередині <body>. Тоді перехоплюють подію touchmove:

javascript
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 на всьому документі і разом зі сторінкою вбивати скрол усередині самої модалки. Перевіряйте ціль події або вішайте слухач точково.
  • Рахувати блокування «глобальним прапорцем»: якщо модалок кілька, потрібен лічильник відкритих вікон, інакше закриття однієї розблокує сторінку під іншою.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.