Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Блокування прокрутки сторінки». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Найпростіший і найнадійніший спосіб це виставити `overflow: hidden` на `<body>` (або `<html>`), зазвичай через CSS-клас на кшталт `.no-scroll`.** Щоб сторінка не «стрибала» вгору, коли її вже було прокручено, до блокування додають фіксацію позиції: `position: fixed` плюс `top: -scrollY`, а при розблокуванні повертають скрол через `window.scrollTo()`. На iOS Safari тач-скрол інколи проходить крізь `overflow: hidden`, тому там додатково перехоплюють `touchmove` з `{ passive: false }`. ```javascript document.body.style.overflow = 'hidden'; // блокуємо скрол document.body.style.overflow = ''; // розблоковуємо ``` **Ключове:** `overflow: hidden` блокує прокрутку, `position: fixed` зберігає позицію, `touchmove` з `preventDefault()` закриває мобільний випадок.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Прокрутку сторінки блокують через 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` на всьому документі і разом зі сторінкою вбивати скрол усередині самої модалки. Перевіряйте ціль події або вішайте слухач точково. - Рахувати блокування «глобальним прапорцем»: якщо модалок кілька, потрібен лічильник відкритих вікон, інакше закриття однієї розблокує сторінку під іншою.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.