26

I'm using the Jquery dialog to open a popup box window on top of a page. When I open the dialog box, I want the general page scrolling to be disabled. To do so, I am doing :

$('body').css({overflow:'hidden'});

when the dialog opens, and:

$('body').css({overflow:'auto'});

when the dialog closes.

This works but when the scrollbar is being removed, the content in the back moves to the right and the result is not nice.

I tried another method, by creating a css class "noscroll", as such :

body.noscroll
{
    position: fixed; 
    overflow-y: scroll;
    width: 100%;
}

then, instead of the previous js code, I'm adding and removing this class to the body on dialog open/close.

Now this works for the scrollbar and the content in the back doesn't move to the right, but with this method the content in the back goes back to the top.

So basically method1 makes the content move to the right, and method2 makes the content move back to the top.

Does anyone know a solution for this? no scroll for the content in the back when the dialog opens, and no movement on disabling scrolling...?

4
  • 1
    Have you considered implementing an absolute positioned 100% div overlay behind the dialog to block all interactions with the page? Commented Sep 3, 2012 at 20:52
  • Good thinking I will try it and post my results! Commented Sep 3, 2012 at 21:06
  • did you find the solution for this question? can you help me? thanks! sorry i speak english not well. Commented Apr 21, 2013 at 18:20
  • Not really, try what I used and what people suggested, and see what works best for you... Commented Apr 22, 2013 at 8:09

6 Answers 6

12
+50

I have made a pretty simple example of my solution.

http://jsfiddle.net/6eyJm/1/

Your popup should be in a box

<div id="shadow">
<div id="popup">
    <a id='close' href="#">Close</a>
</div>

Then put those CSS on de root div

#shadow{
    display: none;
    position: fixed;
    top:0;
    bottom: 0;
    width: 100%;
    height:100%;
    background-color: rgba(0,0,0,0.6);
}

Position fixed is really important since you dont want to see the white border, it will take full window width and not body.

Then there's the little JS trick

$('#open').click(function(e){
    e.preventDefault()
    $('body').width($('body').width());
    $('body').css('overflow', 'hidden');
    $('#shadow').css('display', 'block');
})
$('#close').click(function(e){
    e.preventDefault()
    $('body, #shadow').removeAttr('style')
})

The goal here is to take the body width before removing the scroll bar. Your content will not move.

Hope it help!

Sorry for my english, not my native langage.

Sign up to request clarification or add additional context in comments.

10 Comments

I did a little typo, it shouldnt be $('body #shadow').removeAttr but $('body, #shadow').removeAttr (coma is missing).
when i put open button at middle of list, then click, page scroll is disabled but it goes back to the top.
still not working. when open, the scroll position keep there, but when close, it goes back to top again. My code here: http://jsfiddle.net/ZG8FU/
@TheatreOfSouls The anchor link is scrolling to page to the top. Prevent de default behavior of the link: jsfiddle.net/zujv0g36.
7 years old post saved my day :) Thanks a lot for the idea, works a treat and honestly I don't see the problem with you're English :D
|
9

Remembering the offset should keep your popup at bay;

JSfiddle

HTML

<div id="popupholder">
    <button id="close">Close me</button>
</div>


asd <br />asd <br />asd <br />asd <br />asd <br />
<button class="open">Popup</button>
<br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd<br />
<button class="open">Popup</button>
<br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />
<button class="open">Popup</button>
<br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd<br />
<button class="open">Popup</button>
<br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />

CSS

html, body {
    margin: 0px;
}

#popupholder {
    width: 100%;
    height: 100%;
    position: absolute;
    display: box;
    display: -webkit-box;
    display: -moz-box;
    background-color: rgba(0,0,0,0.75);
    display: none;
}

#close {
    display: block;
    height: 20px;
    margin: 75px auto 0px auto;
}

JavaScript

$(document).ready(function() {
    $('.open').click(function() {
        // Block scrolling
        $('body').css('overflow', 'hidden');

        // Show popup
        var offset = window.pageYOffset;
        //console.log(offset);
        $('#popupholder').css({
            'display': 'block',
            'top': offset + 'px'
        });
    });

    $('#close').click(function() {
        // Enable scrolling
        $('body').css('overflow', 'auto');

        // Hide popup
        $('#popupholder').css('display', 'none');
    });
});

For safety-reasons you could add a very high z-index to your #popupholder, but that's not really relevant to the question.

2 Comments

Thanks for taking time to write code, but i want disable scroll bar, not hide it like facebook popup.
You can add overflow: hidden; to the #popupholder too. Otherwise you can look into similar variants of WebKit's ::-webkit-scrollbar { display: none; } styling. It will access the Shadow DOM and hide the scrollbar fully.
3

I had the same problem this repository helped me no-scroll

Comments

3

This is the best solution I got so far. And believe me I tried all the others and this is the best and the simplest solution I came up with. It works great on Windows devices, which pushes the page from the right to have room for the system scrollbar and IOS devices which don't require space for their scrollbars in the browsers. So by using this you wont need to add padding on the right so the page doesn't flicker when you hide the overflow of the body or html with css.

The solution is pretty simple if you think about it. The idea is to give the window.scrollTop() the same exact position at the moment that a popup is opened. Also change that position when the window resizes ( as the scroll position changes once that happens ).

So here we go...

First lets create the variable that will let you know that the popup is open and call it stopWindowScroll. If we don't do this then you'll get an error of an undefined variable on your page and set it to 0 - as not active.

$(document).ready(function(){
    stopWindowScroll = 0;
});

Now lets make the open popup function witch can be any function in your code that triggers whatever popup you are using as a plugin or custom. In this case it will be a simple custom popup with a simple document on click function.

$(document).on('click','.open-popup', function(){
    // Saving the scroll position once opening the popup.
    stopWindowScrollPosition = $(window).scrollTop();
    // Setting the stopWindowScroll to 1 to know the popup is open.
    stopWindowScroll = 1;
    // Displaying your popup.
    $('.your-popup').fadeIn(300);
});

So the next thing we do is create the close popup function, which I repeat again can be any function you already have created or are using in a plugin. The important thing is that we need those 2 functions to set the stopWindowScroll variable to 1 or 0 to know when it's open or closed.

$(document).on('click','.open-popup', function(){
    // Setting the stopWindowScroll to 0 to know the popup is closed.
    stopWindowScroll = 0;
    // Hiding your popup
    $('.your-popup').fadeOut(300);
});

Then lets create the window.scroll function so we can prevent the scrolling once the stopWindowScroll mentioned above is set to 1 - as active.

$(window).scroll(function(){
    if(stopWindowScroll == 1) {
         // Giving the window scrollTop() function the position on which
         // the popup was opened, this way it will stay in its place.
         $(window).scrollTop(stopWindowScrollPosition);
    }
});

Thats it. No CSS required for this to work except your own styles for the page. This worked like a charm for me and I hope it helps you and others.

Here is a working example on JSFiddle:

JS Fiddle Example

Let me know if this helped. Regards.

3 Comments

Looks good! Could you update your Fiddle link please as it's not working
Updated the JS Fiddle URL.
It looks like the scroll position is kept automatically these days. You can check out my solution (there's a fiddle there).
2

I use these two functions for the same purpose:

function enableBodyScroll() {
  if (document.readyState === 'complete') {
    document.body.style.position = '';
    document.body.style.overflowY = '';

    if (document.body.style.marginTop) {
      const scrollTop = -parseInt(document.body.style.marginTop, 10);
      document.body.style.marginTop = '';
      window.scrollTo(window.pageXOffset, scrollTop);
    }
  } else {
    window.addEventListener('load', enableBodyScroll);
  }
}

function disableBodyScroll({ savePosition = false } = {}) {
  if (document.readyState === 'complete') {
    if (document.body.scrollHeight > window.innerHeight) {
      if (savePosition) document.body.style.marginTop = `-${window.pageYOffset}px`;
      document.body.style.position = 'fixed';
      document.body.style.overflowY = 'scroll';
    }
  } else {
    window.addEventListener('load', () => disableBodyScroll({ savePosition }));
  }
}

How it works:

  1. When you want to disable the scroll with saving the current position, you run disableBodyScroll({ savePosition: true }).

  2. The function check whether the page loaded or not (because user may trigger dialog opening during the loading).

  3. If the page is loaded, it saves current scroll position by setting margin-top on body, then it sets position: fixed; overflow-y: scroll on it to remove scrollbar.

  4. If the page isn't loaded, it adds event listener to run (3.) when the page loads.

For enabling scroll everything is the same, but the function remove styles instead of setting them.

Source of the code: https://github.com/funbox/diamonds/blob/master/lib/body-scroll.ts

Comments

1

you can calculate the difference between the body width, before and after the overflow hidden, and apply it as padding-right to the body

var bodyStartW = $("body").width();
$("body").css("overflow-y" , "hidden");
var bodyEndW = $("body").width();
var bodyMarginL = bodyEndW - bodyStartW;
$("body").css("padding-right" , bodyMarginL);

In Safari you had the same trick for the "html" tag, and margin-right instead of padding-right

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.