How to Disable Scrolling on a Webpage with HTML, CSS, and JavaScript?
Scrolling a webpage while navigating can be controlled by using some JavaScript and CSS or either one of them as well. We shall explore different methods to disable and enable the scrolling functionality of a webpage along with some example code snippets.
Pre-requisite
The prerequisite for understanding this article is the basic understanding of CSS and JavaScript DOM methods like querySelector , and getElementById as well as adding the event listeners to HTML elements.
By Overriding the window.onscroll Function
One of the ways to disable scroll on a webpage is using the window.onscroll event. Let's understand this event.
window.onscroll
The onscroll event on windows is triggered when the window's scrollbar is being scrolled.
We can set the position of this windows.onscroll event to a fixed value then it will prevent the page from scrolling in the vertical or horizontal direction or both.
To do this we need to fix the vertical and horizontal position of the page to the current values which can be done using the following JavaScript functions.
Calculating the current vertical position of the page: To calculate the current vertical scroll position of the web page in pixels document.documentElement.scrollTop and window.pageYOffset functions are used with OR (|) operator because one of them may return 0 value in some of the browsers.
document.documentElement.scrollTop method of JavaScript calculates the number of pixels from the top of the webpage by which the page is scrolled down.
The window.pageYOffset method of JavaScript also calculates the number of pixels from the top of the webpage by which the page is scrolled down. Since some of browsers do not support the former method then this method comes as an alternative.
Calculating the current horizontal position of the page:
To calculate the current horizontal position of the webpage in pixels document.documentElement.scrollLeft and window.pageXOffset values functions are used with the OR (|) operator because one of them may return 0 value in the browsers.
The document.documentElement.scrollLeft method is used to get the number of pixels to the left of the page by which the webpage is displaced to the right.
window.pageXOffset values method is also used to get the number of pixels to the left of the page by which the webpage is displaced to the right but the former method is not supported by some of the browsers, therefore, this method comes as an alternative.
Now, to assign the above-calculated values to the windows.scroll event we may use the window.scrollTo() function and pass the calculated values in this function as arguments to fix the horizontal and vertical position of the webpage.
Let's see the implementation of the above functionality.
Let's try to understand the above snippet. The output of the above code looks like this.
Output:
Here, when we click the Disable Scrolling button then we trigger the function disableScroll() where we are calculating the scroll position in the vertical direction in the scrollTop variable and the scroll position in the horizontal direction in the scrollLeft variable. After calculating these values we assign them to the scroll event of the window using the function called window.scrollTo(scrollTop,scrollLeft) .
When the Enable Scrolling button is clicked then we trigger the function enableScroll() which simply puts the value of the window.scroll event to blank and enables scrolling.
By Setting the Height of the Body to 100% and Overflow to Hidden
Scrolling of the webpage can also be disabled by using only the CSS using the overflow property. In this method, we set the height of the element for which the scroll is disabled to 100% such that it covers all the space of its parent container, and then we set the overflow property to hidden.
For the horizontal scrolling, we use the property overflow-x and set it to hidden.
We shall use JavaScript to add these properties to the HTML document.
Let's see the implementation
Output:
It will have the same effect as with the window.onscroll but with a few differences. Let's discuss those differences.
- It will disable the keyboard scrolling as well. Therefore we won't be able to move up and down using a keyboard, mouse or spacebar, etc.
- It will disable the touch scroll as well
- It will disable the scroll up and down by selecting the text.
Set overflow-x to Hidden to Disable Horizontal Scroll Bar in CSS
For disabling the horizontal scrolling we can set the property overflow-x to hidden along with the height is set to 100%. Everything else remains the same. Let's see the implementation for this.
Output:
Preventing Keyboard Scroll Using JavaScript
Suppose, we want to prevent only the keyboard scroll but want to keep other scrolls, in that case, we need to add a keydown event Listener because this will detect which key is pressed and we can prevent the default behavior of the document if the key pressed is keyboard arrows, spacebar, shift+space bar, pageup, pagedown, etc.
We create an event Listener which takes an event argument and checks if the event(button pressed) has a keyCode equal to some of the keycodes already stored in an array. If it matches with one of them then we call the function preventDefault() and return false. This will disable the scrolling effect using that key.
To enable the scrolling effect we simply remove that eventListner added with that particular keypress.
Let's see the implementation of the above strategy.
Output:
Preventing Touch Scroll Using JavaScript
To prevent the touch scroll, we need to add a touchmove event listener which prevents the default behavior while we perform touch scroll. This can be accomplished by creating a function called disableTouchScroll() which takes a touchmove event and prevents the default behavior using the function preventDefault() and stops the propagation using the stopPropagation() function of the event.
This can be implemented as follows
Applying CSS to Hide the Scrollbar in Website's Code
To hide the scrollbar in the website's code we can use the -ms-overflow-style property in the body element where we can set it to node as well as the -webkit-scrollbar property where we set the display property for this as none, this ultimately hides the scrollbar.
Prevent Scroll On Scrollable Elements [JS & CSS]
If you ever need to temporally disable scrolling on a specific scrollable element, then you will need to use JavaScript or CSS for it. Depending on your use case, you can choose between JavaScript and CSS solutions. Although in general terms the CSS solution is the most adopted one, JavaScript offers you a bit more of control and flexibility and allows you to decide how exactly you want to stop the scrolling.
1. Cancelling scroll using JavaScript
One of the options is to listen to the wheel event on the element you want to prevent the scrolling and then prevent the default behavior as well as stopping the propagation and returning a false value.
Something as simple as this, where #scrollable would be the ID of our scrollable element.
Notice as well that we are using the option
If you need to provide support for IE 11 you might need to add a fallback for the passive event param as it is not supported check if the passive event is supported.
Now, what if we want to enable or disable this dynamically? Here’s an example with a couple of buttons, one to disable the scroll and another one to enable it:
If you want to apply it to multiple elements, it is as easy as iterating over them and applying them to the same function.
Now, take a look at the CSS way because the JS way can get a bit more complicated if we take into account keyboard and touch scrolling.
2. Disabling scroll with only CSS
There’s another way to disable scrolling that is commonly used when opening modals or scrollable floating elements. And it is simply by adding the CSS property overflow: hidden; on the element you want to prevent the scroll.
It is clearly the easiest solution if you want to disable scroll no matter what triggers it (mouse, keyboard, or touch), but at the same time, it won’t give you the flexibility of choosing what to disable and what not.
There’s a couple of differences with the previous way. They can be good for you, or not, depending on your use case:
It will also disable the keyboard scrolling too. So, you won’t be able to move up or down by using the keyboard arrows and space bar, etc.
It will not allow you to scroll up/down by selecting text.
It will disable touch scroll too.
It might also prevent scrolling using "the third button" of the mouse, which is pressing the mousewheel while dragging the mouse. (If anyone can verify this for me that’d be great, as I don’t have a mouse to test it at the moment 🙂 )
So, how do we do it? We create a class that we will toggle whenever we need it and that all it does is preventing the scroll on the element we apply it.
Then, with JavaScript we simply add or remove it when we want:
Here’s a working example:
3. Preventing keyboard scroll using JavaScript
If you decide to go for the JS solution, then you might also want to disable scroll through the keyboard.
In this case, we simply have to listen to the keydown event and prevent the default behavior when we detect they are pressing any key that can trigger a scroll movement, such as the keyboard arrows, spacebar, shift+space bar, pageup, pagedown etc.
And here’s the example:
4. Preventing touch scroll using JavaScript
And of course, we can’t forget about the touch scroll. The CSS solution seems to make things like this much easier for us, but if we need total control over what we allow users to do and what not, then probably the JavaScript version is the way to go.
Regarding touch events, this is pretty similar to canceling the scroll for the wheel event.
We simply have to add the exact same function on a touchmove event listener:
5. Using a npm module to disable scroll
You will also find there are a few components and modules out there that give you this feature out of the box.
Some only apply to the whole document while others allow you to be applied to specific scrollable elements.
Запрет прокрутки при открытии модального окна

Бывало у вас такое? Открываете модальное окно, прокручиваете, а после закрытия оказываетесь на странице в позиции, отличающейся от той, с которой его открывали.
Подобное может происходить из-за того, что модальные окна являются такими же элементами страницы, как и любые другие. Они могут располагаться в фиксированной позиции, не препятствуя работе с остальным содержимым документа.
Порой это не становится проблемой. Например, когда высота содержимого страницы не превышает высоту области видимости экрана пользователя. Однако, в остальных случаях мы неизбежно сталкиваемся с этим. Хорошей новостью является то, что мы можем предотвратить появление скролла с помощью трюка с использованием CSS и JavaScript.
Давайте начнём с чего-нибудь простого
При открытии модального окна можно просто устанавливать элемент body по высоте равным области видимости (viewport) и скрывать вертикальную прокрутку:
Решение имеет право на существование, но если перед открытием модального окна мы прокрутим элемент body , получим небольшую перерисовку содержимого. Ширина области видимости расширяется приблизительно на 15px, что соответствует ширине полосы прокрутки.
Давайте немного отрегулируем правый padding для body , чтобы избежать этого.
Обратите внимание – чтобы это сработало, модальное окно должно быть по высоте меньше области видимости. Иначе полоса прокрутки будет нужна.
Отлично. А что насчёт мобильных?
Это решение отлично работает как на десктопах, так и на мобильных Android-устройствах. Однако, Safari для iOS требует немного больше внимания, поскольку body всё ещё может прокручиваться, когда модальное окно открыто.
Как альтернатива, мы можем задать для body фиксированное позиционирование.
Работает. Теперь body не будет реагировать на свайпы по экрану. Тем не менее, небольшая проблема всё же остаётся. Если кнопка, открывающая модальное окно, находится внизу страницы и чтобы её увидеть, нужно прокручивать страницу, при нажатии на эту кнопку и открытии модального окна, будет происходить автоматическая прокрутка страницы вверх, что может дезориентировать так же, как и фоновая прокрутка body , от которой мы пытаемся избавиться.
Вот поэтому нам не обойтись без JavaScript
Можем использовать JavaScript, чтобы избежать всплытия события прикосновения к экрану. Все мы знаем, что при открытии модального окна, у него должен быть фоновый слой. К сожалению, в iOS метод stopPropagation() с событиями прикосновения работает немного неуклюже. Но у preventDefault() таких проблем нет. Это значит, что мы должны добавить обработчики событий к каждому DOM-элементу внутри модального окна, а не только к слою подложки или самому модальному окну. Хорошая новость в том, что много JavaScript-библиотек могут делать это, включая старый добрый jQuery.
Ах да, и ещё кое-что. Что если нам нужна прокрутка внутри модального окна? Нам всё ещё нужно вызвать реакцию на событие свайпа, но при достижении верха или низа модального окна, нам всё ещё нужно предотвращать всплытие. Кажется очень сложным (?? так что мы ещё не полностью выкарабкались).
Давайте улучшим фиксированный body
Вот с чем мы работали:
С помощью JavaScript можно вычислить положение прокрутки страницы, и добавлять это значение в CSS. Благодаря этому body не будет прокручиваться обратно в начальную позицию.
Данное решение работает, но после закрытия окна всё ещё происходит небольшой сдвиг. А именно, похоже, когда модальное окно открыто и для body задано фиксированное позиционирование, страница уже теряет положение прокрутки. Следовательно, нам нужно восстановить положение. Давайте изменим JavaScript, чтобы учитывать этот момент.
Вот и всё. Теперь body не будет прокручиваться при открытом модальном окне, а положение прокрутки сохраняется и при открытии и при закрытии модального окна.
First of all — WHY one have to fight the scroll?
![]()
In short — because sometimes you have to block all the interactions with the page. Page should be completely irresponsible. Thats the rule. Simple rule.
- You shall not be able to click on it. Not be able to click.
- Move the focus, or press keys. Not be able to press.
- Scroll it. Not be able to scroll.
Ok then — WHEN it should be irresponsible?
When you should be focused not on the page, but only on some part of it.
For example Modals — small(or big) boxes, floating in the middle of the screen. The rest of the page could be even dimmed, cos…
the Modal is the only entity you should operate with.
I am a bit surprised, that MDN Modal Dialog a11n Article highlights the need of focus management and proper aria attributes, but not scroll blocking.
And not text-to-speech blocking via inert or aria-hidden, right now implemented only in reach-ui and smooth-ui
May be it’s not super clear why modal should block page scroll. Scroll seems to be ok, as long you will see it.
While you are understanding what you are scrolling the page. And while it is what you wanted to do.
Thus another great example, to explain why scroll should be blocked, is Fullscreen Modal Dialog, or “FocusedTask”. Something which will consume all your attention.
Once opened it will consume all the screen, and you will not see and be able interact with the main page content any more. But you will able to scroll it.
Need more? Ok — “onboarding” component, which guides you thought the page.
Let’s imagine — you are able to scroll the page. And you will scroll the page. And “spotlights” will be scrolled out. And your customer will be lost in the partially disabled application……
How to block a scroll?
Oh! That’s super easy — style="overflow:hidden" on body.
overflow:hidden will remove the scrollbars (they are hidden), and block the scroll, as long this overflow mode is not scrollable. This is how CSS works.
But… Safari
Yep— it does not work on Mobile Safari.
- Safari ignores overflow on body, allowing you to touch-scroll it. And this is something you can touch-n-feel only on the real iPhone, not Chrome emulation.
- It will work as a shit, especially for forms, as long “touch-scroll” is “drag-n-drop” action for some tags, and you will not be able to scroll thought them.
The fix for the second problem is simple — just change scroll behavior:
> This might be something you want enabled by default!
And the fix for the first problem is also… simple… — event.preventDefault .
The only problem — which element to listen, and which event to prevent. All events inside the modal should go life, all events outside should be blocked, and all those events could bubble from “ok-ish” elements, to the not-ok-ish.
So — for every event, which might cause scroll, you have to calculate something, lets call it scrollability, and block event which might scroll something you don’t want to be scrolled.
I would say — use external libraries to handle this.
Conclusion
So — use overflow:hidden on body to kill the scroll on Desktop and Android browsers, and prevent events to mitigate Safari.
Actually not, we missed one point. Scroll bars!
Kill the The Scroll Bar!
Scroll is disabled only when scroll bars are disabled.
Question — you had scroll bar, and now you have removed it. That is left?
Scroll bars disappeared! Completely!
As result you page now 17 pixels wider, and all your content “jumped”. Thats parasite and quite unpleasant jittery effect we shall not stand.
It is easy to mitigate it — detect Scroll bar width, as set as a padding to body.
And last “bonus” stuff — properly handle width of the body: normal elements must have “right” there it was before, ie with “gap”, while “right” for elements inside lock should be on the window right.
Filling “gap” with paddingRight.
Notice — absolute positioned elements stick to window edge. That might be something you want — display element from edge to edge. But, you know, content of those elements will “shake” and probably this is not what you really want.
Filling the “gap” with marginRight.
Notice — first(red), and third(no name) element are not changing their position, while second ( position:fixed ) still stick to the edge. It’s fixable — as long as we “fixed” body — we might fix any other element.
Probably you need this behavior.
Fun fact — majority of libraries uses paddings. Any ideas why?
Today there is only one library (and sorry — it’s based on React, feel free to fork and adopt it to your stack) which does it right: