56

is it possible to disable scrolling in browser (just for browser's scrollbars) while a jQuery UI modal dialog is open.

Note: I do want scrolling to be enabled inside the dialog

Omu
  • 69,856
  • 92
  • 277
  • 407
  • So how did you enable the scroll inside your dialog using correct answer? – Feanor Sep 25 '14 at 14:01
  • @Feanor atm I'm setting css position:fixed for the dialog div, so even though the browser scrolls the dialog stays fixed, and inside the dialog the scroll works with default css (overflow: auto) – Omu Sep 26 '14 at 07:57
  • JSBin reference for css overflow http://jsbin.com/yicidecodu/1/edit?html,css,output – Naveen Kumar Alone Nov 21 '14 at 11:16

16 Answers16

76
$(formObject).dialog({
 create: function(event, ui) {
  $("body").css({ overflow: 'hidden' })
 },
 beforeClose: function(event, ui) {
  $("body").css({ overflow: 'inherit' })
 }
});

Or as I allude to in the comment below:

var dialogActiveClassName="dialog-active";
var dialogContainerSelector="body";

$(formObject).dialog({
 create: function(event, ui) {
   $(dialogContainerSelector).addClass(dialogActiveClassName);
 },
 beforeClose: function(event, ui) {
   $(dialogContainerSelector).removeClass(dialogActiveClassName);
 }
});

But actually to be honest, you should ensure that creating a dialog bubbles an event up to your window object where you'd be watching for said events, roughly something like this pseudo:

var dialogActiveClassName="dialog-active";
var dialogContainerSelector="body";
$(window).on("event:dialog-opened", function(){
    $(dialogContainerSelector).addClass(dialogActiveClassName);
});
$(window).on("event:dialog-closed", function(){
    $(dialogContainerSelector).removeClass(dialogActiveClassName);
});
airtonix
  • 4,772
  • 2
  • 38
  • 36
  • 3
    This only hides scroll bars, it doesn't prevent scrolling – Chaosphere2112 Dec 07 '11 at 15:09
  • 9
    Also worked for me. If you want to open the dialog later (not on page load) then bind the scrollbar hiding to the 'open' event instead of 'create'. – Germstorm Nov 15 '12 at 09:48
  • 2
    At first, it would not work for my project while using IE8. However, I got it to work by changing the above selector to $("html, body") so the style would be applied to both the body element and the HTML element. For some reason this made it start working for me! Just mentioning this here in case anyone else runs into this problem.... hopefully it will save someone time. The only problem I have with this overall solution is when the Y-axis scroll bar disappears, it creates a slight horizontal screen jitter. (When the jquery dialog opens and when it closes) – Jason Parker Mar 19 '13 at 18:38
  • 1
    actually the "Best Practice"(tm) way to deal with this is to toggle a class name on what ever container object wraps around your dialog element. – airtonix Aug 06 '13 at 06:11
  • 1
    I would recommend putting the function to prevent scroll on the `open` event instead of the `create` event. For example, if you have a button that shows the modal dialog, the body won't be able to scroll if you have already created the dialog, even if it's not showing. – Mike Jan 23 '14 at 00:12
  • 'inherit' does not always return scroll function on close. I had better luck with 'auto' and '' – carruthd May 09 '14 at 15:01
  • This worked for me... Used $(window).on("dialogopen", function(){ $("body").addClass("antiscroll"); }); $(window).on("dialogbeforeclose", function(){ $("body").removeClass("antiscroll"); }); – Joel Caton Jul 11 '19 at 22:14
47

I needed to do exactly the same thing, do it simply by adding a class to the body:

.stop-scrolling {
  height: 100%;
  overflow: hidden;
}

Add the class then remove when you want to re-enable scrolling, tested in IE, FF, Safari and Chrome.

$('body').addClass('stop-scrolling')
hallodom
  • 6,429
  • 1
  • 23
  • 19
28

JS Bin reference for CSS overflow

Simply Add

$('body').css('overflow','hidden');

to your function that shows the modal.

And

$('body').css('overflow','scroll');

to your function that closes the modal.

Naveen Kumar Alone
  • 7,536
  • 5
  • 36
  • 57
  • 2
    I cant have enough appreciation for a simple solution. Thanks! – CodeGuyRoss Jul 26 '15 at 20:39
  • the best solution! – Marco Alves Apr 01 '17 at 02:55
  • For those who use primefaces and want to prevent body of the website to scroll while modal dialog is shown, just put these two into the onHide and onShow attributes of p:dialog e.g. onHide="$('body').css('overflow','scroll');" onShow="$('body').css('overflow','hidden');" – hocikto Feb 22 '18 at 13:12
7

Here is the best that I could come up with to solve this issue (I had the same problem) using the functions referenced in the answer by JasCav above (these functions):

dialogClass: 'dialog_fixed',
create: function(event, ui) {
    disable_scroll(); // disable while dialog is visible
    $('#dialog_form').hover(
        function() { enable_scroll(); }, // mouse over dialog
        function() { disable_scroll(); } // mouse not over dialog
    );
},
beforeClose: function(event, ui) {
    enable_scroll(); // re-enable when dialog is closed
},

the css is:

.dialog_fixed { position:fixed !important; }

and it just keeps the dialog fixed on the page, which maybe we don't need anymore.

This allows mouse scrolling while the mouse is over the dialog, but not when it is outside the dialog. Unfortunately it will still scroll the main page when the mouse is over the dialog and you scroll past the end of the content inside the dialog (in IE right away, in Safari and Firefox after a short delay). I would love to know how to fix this.

I tested this in Safari 5.1.5, Firefox 12, and IE 9.

Community
  • 1
  • 1
Craig Nakamoto
  • 2,075
  • 2
  • 18
  • 19
6

Stops scrolling, adjusts dialog position and returns user to part of page they were viewing after they close the dialog

$('<div/>').dialog({
    open : function(event, ui) { 
        $('html').attr('data-scrollTop', $(document).scrollTop()).css('overflow', 'hidden');
        $(this).dialog('option','position',{ my: 'center', at: 'center', of: window });
    },
    close : function(event, ui) { 
        var scrollTop = $('html').css('overflow', 'auto').attr('data-scrollTop') || 0;
        if( scrollTop ) $('html').scrollTop( scrollTop ).attr('data-scrollTop','');
    }
});
oLinkWebDevelopment
  • 1,841
  • 15
  • 8
  • This is the functionality that's expected when you want to stop a page from scrolling when the dialog is opened. If you're hovering over something when the dialog opens and want to retain the hover state, best way is to use add/remove class for the styles. – PBwebD Feb 03 '16 at 05:07
4

You can't disable scrolling completely, but you can stop scrolling with the mouse wheel and the buttons that typically perform scrolling.

Take a look at this answer to understand how that is done. You could call these functions on the create event and return everything to normal, on close.

Community
  • 1
  • 1
JasCav
  • 34,458
  • 20
  • 113
  • 170
  • 19
    This is a nice solution, but it disables scrolling in the dialog as well, but if I understand the question correctly, we want the scrolling to work in the dialog, just not anywhere else. – Craig Nakamoto May 02 '12 at 19:03
  • @CraigNakamoto, I think you can attach the eventListener to the dialog after then. So the scroll will be disabled in document level, but the dialog still have a event listener for scroll. It will be something like `$(document).('on', '.dialog', function(){ /*scroll code*/ });` – lhrec_106 May 13 '16 at 02:01
3

Just a modification on an answer posted above by hallodom

$('body, html').addClass('stop-scrolling')

browser scrolling wasn't disabled until I added html.

.stop-scrolling {
  overflow: hidden;
}

by removing height: 100%, the bump-to-top effect was removed.

Tested on Chrome, Firefox and Safari.

SilentJ
  • 31
  • 1
2

Old post but the way I did it was:

open: function(event, ui) {                
     $('html').css('overflow', 'hidden');
     $('.ui-widget-overlay').width($(".ui-widget-overlay").width() + 18);
     },
close: function(event, ui) {
     $('html').css('overflow', 'hidden');
}

This seems to work quite nicely

hcharge
  • 1,216
  • 2
  • 24
  • 43
2

Searched for a long long time. Finally the follow link saves me. Hope it's helpful to others.

It uses a container for the main body. The scrolling in dialog won't affect the background container.

http://coding.abel.nu/2013/02/prevent-page-behind-jquery-ui-dialog-from-scrolling/

horizon1711
  • 152
  • 1
  • 5
2

Create this css class:

.stop-scrolling {
    overflow:hidden;
    height: 100%;
    left: 0;
    -webkit-overflow-scrolling: touch;
    position: fixed;
    top: 0;
    width: 100%;
}

Then add this to your dialog init:

$("#foo").dialog({
    open: function () {
        $('body').addClass('stop-scrolling');
    },
    close: function () {
        $('body').removeClass('stop-scrolling');
    },
    // other options
});

If you are already using open: and close: to call other functions, just add the addClass and removeClass lines in the appropriate place.

Kirk Ross
  • 6,413
  • 13
  • 61
  • 104
2
$(settings.dialogContentselector).dialog({
        autoOpen: false,
        modal: true,
        open: function( event, ui ) {
            $("html").css({ overflow: 'hidden' });
            $("body").css({ overflow: 'hidden' });
        },
        beforeClose: function( event, ui ) {
            $("html").css({ overflow: 'auto' });
            $("body").css({ overflow: 'auto' });
        }
    });
Flyke
  • 347
  • 3
  • 5
1

try this one. it being used by http://jqueryui.com itself

html { overflow-y: scroll; }

Izzati Ali
  • 31
  • 3
1

create: event Makes scrollbars disappear when page loading for first time I change it with open: and working now like a charm

Otto Kanellis
  • 3,629
  • 1
  • 23
  • 24
0

A better solution avoiding body jumps to top when popup is closed:

$(document).ready(function(){
  var targetNodes         = $(".cg-popup");
  var MutationObserver    = window.MutationObserver || window.WebKitMutationObserver;
  var myObserver          = new MutationObserver (mutationHandler);
  var obsConfig           = { attributes : true, attributeFilter : ['style'] };
  // ADD A TARGET NODE TO THE OBESERVER. CAN ONLY ADD ONE NODE AT TIME
  targetNodes.each ( function () {
      myObserver.observe (this, obsConfig);
  } );
  function mutationHandler (mutationRecords) {
    var activate_scroll = true;
    $(".cg-popup").each(function( index ) {
      if($(this).css("display") != "none"){
        $('html, body').css({'overflow-y': 'hidden', 'height': '100%'});
        activate_scroll = false;
        return;
      }
    });
    if(activate_scroll){
      $('html, body').css({'overflow-y': 'auto', 'height': 'auto'});
    }
  }
});
-1

This issue is fixed, Solution: Just open your bootstap.css and change as below

body.modal-open,
.modal-open .navbar-fixed-top,
.modal-open .navbar-fixed-bottom {
margin-right: 15px;
}

to

body.modal-open,
.modal-open .navbar-fixed-top,
.modal-open .navbar-fixed-bottom {
/margin-right: 15px;/
}

Please view the below youtube video only less than 3min your issue will fix... https://www.youtube.com/watch?v=kX7wPNMob_E

-3

It is because you have to add modal: true in your code; this prevent user from interacting with background.

JSK NS
  • 3,346
  • 2
  • 25
  • 42
Hal
  • 1