How to Disable Scroll Without Hiding It

How to disable scroll without hiding it?

If the page under the overlayer can be "fixed" at the top, when you open the overlay you can set

body { position: fixed; overflow-y:scroll }

you should still see the right scrollbar but the content is not scrollable. When you close the overlay just revert these properties with

body { position: static; overflow-y:auto }

I just proposed this way only because you wouldn't need to change any scroll event


You could also do a slight improvement: if you get the document.documentElement.scrollTop property via javascript just before the layer opening, you could dynamically assign that value as top property of the body element: with this approach the page will stand in its place, no matter if you're on top or if you have already scrolled.


.noscroll { position: fixed; overflow-y:scroll }


$('body').css('top', -(document.documentElement.scrollTop) + 'px')

Disable scrolling but keep scrollbar CSS

Instead of changing the css, which will remove the scrollbar, and as you said change the layout of the page, try calling a jquery function instead.

// call your pop up and inside that function add below
$('body').on('scroll mousewheel touchmove', function(e) {
return false;

then when you close the modal, call the same function but replace on with off

Disable scroll but without hiding the scroll bar for React JS?

You could just add an event to the onscroll, and then keep a track of the current scrollTop, scrollLeft (if you need to handle horizontal too), and then when you don't want scroll just reset the scroll to these stored values.

eg. If you run the snippet below when the large checkbox is checked, scrolling is disabled.

const div = document.querySelector('div');
const cb = document.querySelector('input');

let lastY = 0;

div.innerText = new Array(3000).fill().map(m => 'hello ').join(' ');

div.addEventListener('scroll', (e) => {
if (cb.checked) { = lastY;
} else lastY =;

cb.addEventListener('click', () => {
div {
height: 150px;
overflow: auto;
input {
position: fixed;
top: 50px;
left: 50px;
transform: scale(4);
<input type="checkbox"/>

Disable body scroll but don't hide scrollbar

One approach that's both very simple and effective is to not have the main content in the body itself, but a wrapper that's a sibling with the overlay. With this approach you can toggle the overlay whenever necessary without affecting the scroll of the content element.

var e = document.getElementById('overlay');document.body.onclick = function() { = (! || === 'block') ? 'none' : 'block';};
html,body,#content {  height: 100%;  margin: 0;}#content {  overflow: auto;}#high {  height: 800px;}#overlay {  position: absolute;  height: 100%;  width: 100%;  background: rgba(0, 0, 0, 0.5);}
<div id="overlay"></div><div id="content">  Long content resides in this container  <div id="high"></div>  And the long content ends here</div>

Prevent body scrolling but allow overlay scrolling


Looking at current implementation of the pinterest site (it might change in the future), when you open the overlay a noscroll class is applied to the body element and overflow: hidden is set, thus body is no longer scrollable.

The overlay (created on-the-fly or already inside the page and made visible via display: block, it makes no difference) has position : fixed and overflow-y: scroll, with top, left, right and bottom properties set to 0: this style makes the overlay fill the whole viewport.

The div inside the overlay is instead just in position: static then the vertical scrollbar you see is related to that element. As a result the content is scrollable but overlay remains fixed.

When you close the zoom you hide the overlay (via display: none) and then you could also entirely remove it via javascript (or just the content inside, it's up to you how to inject it).

As a final step you have to also remove the noscroll class to the body (so the overflow property returns to its initial value)


Codepen Example

(it works by changing the aria-hidden attribute of the overlay in order to show and hide it and to increase its accessibility).


(open button)

<button type="button" class="open-overlay">OPEN LAYER</button>

(overlay and close button)

<section class="overlay" aria-hidden="true">
<h2>Hello, I'm the overlayer</h2>
<button type="button" class="close-overlay">CLOSE LAYER</button>


.noscroll { 
overflow: hidden;

.overlay {
position: fixed;
overflow-y: scroll;
top: 0; right: 0; bottom: 0; left: 0; }

[aria-hidden="true"] { display: none; }
[aria-hidden="false"] { display: block; }

Javascript (vanilla-JS)

var body = document.body,
overlay = document.querySelector('.overlay'),
overlayBtts = document.querySelectorAll('button[class$="overlay"]');

[], function(btt) {

btt.addEventListener('click', function() {

/* Detect the button class name */
var overlayOpen = this.className === 'open-overlay';

/* Toggle the aria-hidden state on the overlay and the
no-scroll class on the body */
overlay.setAttribute('aria-hidden', !overlayOpen);
body.classList.toggle('noscroll', overlayOpen);

/* On some mobile browser when the overlay was previously
opened and scrolled, if you open it again it doesn't
reset its scrollTop property */
overlay.scrollTop = 0;

}, false);


Finally, here's another example in which the overlay opens with a fade-in effect by a CSS transition applied to the opacity property. Also a padding-right is applied to avoid a reflow on the underlying text when the scrollbar disappears.

Codepen Example (fade)


.noscroll { overflow: hidden; }

@media (min-device-width: 1025px) {
/* not strictly necessary, just an experiment for
this specific example and couldn't be necessary
at all on some browser */
.noscroll {
padding-right: 15px;

.overlay {
position: fixed;
overflow-y: scroll;
top: 0; left: 0; right: 0; bottom: 0;

[aria-hidden="true"] {
transition: opacity 1s, z-index 0s 1s;
width: 100vw;
z-index: -1;
opacity: 0;

[aria-hidden="false"] {
transition: opacity 1s;
width: 100%;
z-index: 1;
opacity: 1;

Disable Scrolling on Body

Set height and overflow:

html, body {margin: 0; height: 100%; overflow: hidden}

Deactivate body's scrolling but keep scroll bar

This is the only CSS you will ned to force the scrollbars:

overflow-y: scroll;

The scrollbars will be disabled if the content is smaller than the window, so you will have to use some script to resize the body to be at least 1px less then the window height:

$("body").css({ "height" : ($(window).height() - 1) + 'px', "overflow": "hidden" });

Disable horizontal scrolling without overflow hidden

Simply remove all the width you specified as this is the default behavior of block element to take 100% of width. And you need to pay attention as 100vh is not equal to 100%. The first one include the calculation of scrollbar :

* {  margin: 0;  padding: 0;  box-sizing: border-box;  max-width: 100vw;  font-family: 'Montserrat', sans-serif;  font-weight: 400;}
#nav { height: 100px; padding: 0 2vw; font-weight: 700;}
.p5_container { height: calc(100vh - 100px - 150px); background-color: beige;}
.arrow { height: 150px; background-color: #6195B2;}
<body>  <header id="nav">    <ul>      <li><a href="#">Circle</a></li>      <li><a href="#">Square</a></li>      <li><a href="#">Line</a></li>    </ul>  </header>
<div id="p5_banner" class="p5_container"></div>
<div class="arrow"></div> <div id="p5_circle" class="p5_container"></div>
<div class="arrow"></div> <div id="p5_square" class="p5_container"></div>
<div class="arrow"></div> <div id="p5_line" class="p5_container"></div></body>

Related Topics

Leave a reply