48

If I open a modal dialog, through Twitter Bootstrap, I've noticed that it pushes all the html content of the page (i.e., in the container) to the left a little bit, and then puts it back to normal after closing itself. However, this only happens if the browser width is large enough to not be on the "mobile" (i.e., smallest) media query. This occurs with the latest versions of FF and Chrome (haven't tested other browsers).

You can see the problem here: http://jsfiddle.net/jxX6A/2/

Note: You have to increase the width of the "Result" window so it switches to the "med" or "large" media query css.

I have setup the HTML of the page based upon the examples shown on Bootstrap's site:

<div class='container'>
    <div class='page-header'>
        <h4>My Heading</h4>
    </div>
    <div id='content'>
        This is some content.
    </div>
    <div class='footer'>
        <p>&copy; 2013, me</p>
    </div>
</div>

I'm guessing this is not supposed to happen, but I'm not sure what I've done wrong.

EDIT: This is a known bug, for more (and up-to-date) information, please see: https://github.com/twbs/bootstrap/issues/9855

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
EleventyOne
  • 7,300
  • 10
  • 35
  • 40
  • Isn't it caused by the scrollbar appearing on the right side when you open the modal? You would need to give body overflow:hidden when you open the modal to prevent that and overflow:inherit when you close it. – clime Oct 12 '13 at 17:46
  • 1
    @clime Doh! I'm sure you're right about why it's happening. Unfortunately, adding `overflow:hidden` to `body` in CSS doesn't seem to prevent it :( – EleventyOne Oct 12 '13 at 17:51
  • @EleventyOne definitive fix here: http://stackoverflow.com/a/23851892/114029 – Leniel Maccaferri May 25 '14 at 04:03

30 Answers30

45

For bootstrap 3.x.x.

I have found a solution, that works with 100% CSS and no JavaScript.

The trick is to show the scrollbar for modal over the scrollbar of html content.

CSS:

html {
  overflow: hidden;
  height: 100%;
}
body {
  overflow: auto;
  height: 100%;
}

/* unset bs3 setting */
.modal-open {
 overflow: auto; 
}

Here is an online example: http://jsbin.com/oHiPIJi/43/

I tested it on Windows 7 with:

  • FireFox 27.0
  • Chrome 32.0.1700.107 m
  • IE 11 in Browser Mode 8, 9, 10, Edge (Desktop)
  • IE 11 in Browser Mode 8, 9, 10, Edge (windows phone)

One new little issue I found with IE:

IE has background (=body) scrolling with mouse wheel, if there is nothing more to scroll in the foreground.

Take care with position:fixed!

Because of the nature of this workaround, you need extra care for fixed elements. For example the padding for "navbar fixed" needs to be set to html and not to body (how it is described in bootstrap doc).

/* only for fixed navbar: 
* extra padding setting not on "body" (like it is described in docs), 
* but on "html" element
* the value used depends on the height of your navbar
*/
html {
  padding-top: 50px;
  padding-bottom: 50px;
}

Alternative with wrapper

If you do not like setting overflow:hidden on html (some people don't like this, but it works, is valid and 100% standards compliant), you can wrap the content of body in an extra div. You can use it as before by using this approach.

body, html {
  height: 100%;
}
.bodywrapper {
  overflow: auto;
  height: 100%;
}

/* unset bs3 setting */
.modal-open {
 overflow: auto; 
}

/* extra stetting for fixed navbar, see bs3 doc
*/
body {
  padding-top: 50px;
  padding-bottom: 50px;
}

Here is an example: http://jsbin.com/oHiPIJi/47/

Update:

Issues in Bootstrap:

Update 2: FYI

In Bootstrap 3.2.0 they add a workaround to modal.js that tries to handle the issues with Javascript for every invoke of modal.prototype.show(), Modal.prototype.hide() and Modal.prototype.resize(). They add 7 (!) new methods for that. Now about 20% of code from modal.js tries to handle just that issue.

Yvonne Aburrow
  • 2,602
  • 1
  • 17
  • 47
TLindig
  • 48,010
  • 3
  • 28
  • 31
  • 1
    The original bug has been [fixed in Bootstrap v3.2.0+](https://github.com/twbs/bootstrap/pull/13103) but still seems to happen in [ui-angular](http://angular-ui.github.io/bootstrap/#/modal). This CSS fix worked for me (using it until ui-angular is updated). – Nate Barbettini Nov 18 '14 at 16:12
  • 1
    What I did, was to add just .modal-open { overflow: auto !important; } and to comment some bootstrap code Modal.prototype.setScrollbar = function () { var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) //if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) } – danpop Feb 11 '15 at 14:00
  • 8
    Its not working in my case. Solution worked for me was body.modal-open { padding-right: 0px !important; overflow-y: auto; } – Manjay_TBAG Apr 16 '15 at 10:27
  • @TBAG It helps, but it doesn't work for me... It pushes my HTML to the left, but only once, and not as much as before... It still moves it about 5-10px, any clue on how to fix this? – Albert MN. Oct 16 '15 at 17:34
  • Doesn't work in Firefox for me. It's fixed now in the other Browsers. – maracuja-juice Aug 16 '16 at 11:10
  • Works fine mate. Good staff! – thanos_zach Oct 28 '19 at 12:46
41

Try this:

body.modal-open {
    overflow: auto;
}
body.modal-open[style] {
    padding-right: 0px !important;
}

.modal::-webkit-scrollbar {
    width: 0 !important; /*removes the scrollbar but still scrollable*/
    /* reference: http://stackoverflow.com/a/26500272/2259400 */
}
Jimmy Ilenloa
  • 1,989
  • 21
  • 21
14

It is actually caused by the following rule in bootstrap.css:

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

I am not exactly sure why it behaves like that (perhaps to account for scrollbar somehow) but you can change the behaviour with this:

body.modal-open {margin-right: 0px}

EDIT: Actually, this is a reported issue in bootstrap: https://github.com/twbs/bootstrap/issues/9855

clime
  • 8,695
  • 10
  • 61
  • 82
  • Hmmm, that's interesting. There's no movement at all on the page when I add that (http://jsfiddle.net/jxX6A/18/). I'm only learning bootstrap now so I wonder if I can change that without it (negatively) affecting Bootstrap in other ways. – EleventyOne Oct 12 '13 at 18:17
  • Thanks for finding that bug report. Based upon the discussion in that thread, it looks like changing the `margin-right` property will have a deleterious effect on other aspects of Bootstrap :( – EleventyOne Oct 12 '13 at 18:28
  • well, i wouldn't say other aspects. Rather in some browsers, it might cause pulling the content to the right when modal is open:). So you can choose what you prefer :). Btw. partial fix should be in bootstrap 3.0.1. The full fix is coming in 3.0.2 – clime Oct 12 '13 at 18:30
  • Indeed. However, the other answer (`overflow-y:scroll` in `body`) seems to prevent both of those issues, only moving the content a tiny bit, and that matches what occurs on bootstrap's own example page. ATM, that seems like the best approach to me. What do you think? – EleventyOne Oct 12 '13 at 18:31
  • I am not sure, as the half-fix they used my approach: https://github.com/twbs/bootstrap/commit/352532cd63a2d8e03ba7db806aa3bd110c023532 so probably it is not a bad idea. But overflow-y:scroll on body ... probably allright, I would try more browsers and picked whatever works better :). – clime Oct 12 '13 at 18:35
  • Yeah, I'll watch the boostrap github page to see how this plays out. Thanks for your help :) – EleventyOne Oct 12 '13 at 18:38
  • Using BS 3.1.1 the problem doesn't seem to happen in that jsFiddle (no matter if you put margin-right:0 or not). But I'm experiencing the problem in my web app. Don't know why. Any final solution to this? – empz Mar 19 '14 at 21:25
6

When the model opens, a padding of 17px to the right of the body. The code below should resolve that issue.

body {
padding-right: 0px !important;
}
Jeacovy Gayle
  • 447
  • 9
  • 9
  • 1
    The modals on my site using BS 3.3.7 were adding exactly 17px to the body tag, and this solved the problem. Thanks! – Avi Tevet Apr 19 '17 at 18:18
4

Here's the fix proposed by user yshing that really FIXED it for me while using Bootstrap v3.1.1 and Google Chrome 35.0.1916.114m. The fix comes from a GitHub issue thread regarding this matter:

.modal
{
    overflow-y: auto;
}

.modal-open
{
   overflow:auto;
   overflow-x:hidden;
}

The fix will land only in Bootstrap 3.2 as desbribed by mdo.

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
  • Note: This is NOT the OFFICIAL fix. The official fix is https://github.com/twbs/bootstrap/commit/0907244256d923807c3a4e55f4ea606b9558d0ca – cvrebert May 25 '14 at 04:20
  • Unfortunately this does not prevent the body to show the unaesthetic right-padding while the modal is open. – Luca Fagioli May 05 '15 at 17:53
  • Not working as expected for me. Yes - there is no shift. But I got two vertical scrollbars on the right. – kashesandr Jul 09 '15 at 11:06
3

To prevent the page from shifting in similar instances - for example an accordion opening that goes past the bottom of the page - I add this in CSS:

body {
    overflow-y: scroll;
    height: 100%;
}

The overflow-y: scroll forces the scrollbar to present at all times. To be honest, I can't remember why I put height:100% in there... but you don't seem to require it for this problem.

Demo: http://jsfiddle.net/jxX6A/8/

There is still a little movement. But that seems to be present on Bootstrap's own example page: http://getbootstrap.com/javascript/#modals

So I'm guessing you're stuck with it... but it's still far better than what you were seeing initially.

EDIT: I might be concerned that adding these styles would interfere with other Bootstrap stuff, as I haven't used it myself, so you might want to double check on that.

a.real.human.being
  • 878
  • 2
  • 6
  • 17
  • Yeah, this does seem to make the dialogs work as they do on bootstrap's own example page. Looking at the `boostrap.css` file, I see that they have `overflow-y:scroll` set in the `.modal` class itself too. I'm really not sure what the right approach is here. – EleventyOne Oct 12 '13 at 18:20
  • This is what I wanted ALL the time, and had searched high and low but couldn't find it(maybe because of lack of correct phrasing of the problem), Thanks man, I was totally bogged down by the annoying horizontal jittery effect caused by the scroll bar disappearing and reappearing, to a point It actually had me reconsidering other options than bootstrap. – Mohd Abdul Mujib Jan 23 '14 at 12:11
3

You just edit .modal-open class form bootstrap.min.css file, I thin it's will be ok .modal-open{overflow:auto}

The over-flow:hidden is set there , you just set over-flow:auto .

altaf
  • 64
  • 2
3

i have faced same problem and following solution

.modal-open {
    overflow: visible;
}

.modal-open, .modal-open .navbar-fixed-top, .modal-open .navbar-fixed-bottom {
    padding-right:0px!important;
}
Vinay Pandya
  • 3,020
  • 2
  • 26
  • 42
2

I have same problem and I got solution that is work for me....

body .modal-open {
  padding-right: 0% !important;
  overflow-y: auto;
}

place this code at top of your style.css file

Igor Ivancha
  • 3,413
  • 4
  • 30
  • 39
Anakbhai Gida
  • 668
  • 3
  • 20
2

A lot has changed since bootstrap 3.3.6 so the solutions above may not suffice.

To solve this, look at the setScrollbar function in bootstrap.js (or bootstrap-min.js of course), you will immediately notice that bootstrap is adding padding-right to the body element setting its value to a worked out value of scrollbarWidth plus existing padding-right on the body (or 0 if not).

If you comment out the below

//this.$body.css('padding-right', bodyPad + this.scrollbarWidth)

In your css override bootstrap modal-open class with the below

.modal-open{
  overflow:inherit;
 }

Folks have suggested overflow-y: scroll; the problem with this is that your content shifts if scroll bar does not exists in the first place.

NB As per http://getbootstrap.com/javascript/#modals, always try to place a modal's HTML code in a top-level position in your document

pmanOnu
  • 21
  • 2
1

Found this answer in TB issues

just by adding this below css that small movement will be fixed

body, .navbar-fixed-top, .navbar-fixed-bottom {
  margin-right: 0 !important;
}

Credits to https://github.com/tvararu

Venkata K. C. Tata
  • 5,539
  • 4
  • 22
  • 35
1

I use Bootstrap v3.3.4 and see this problem, I understood that Bootstrap modal add 17px padding right to the body, so just simply use following code:

body {
    padding-right: 0 !important;
}
Milad Rahimi
  • 3,464
  • 3
  • 27
  • 39
1

No solution here fixed my issue. But following Css I got from Github worked for me.

body.modal-open {
padding-right: 0px !important;
overflow-y: auto;
}
Manjay_TBAG
  • 2,176
  • 3
  • 23
  • 43
1

Just do this simply and thats all

.modal-open {
padding-right: 0 !important;
}

Works for me. Short and does the job.

Joshua
  • 818
  • 11
  • 12
0

This is a reported issue to bootstrap: https://github.com/twbs/bootstrap/issues/9855

And this is my temporary quick fix and it's work using fixed top navbar, only using javascript. Load this script along with your page.

$(document.body)
.on('show.bs.modal', function () {
    if (this.clientHeight <= window.innerHeight) {
        return;
    }
    // Get scrollbar width
    var scrollbarWidth = getScrollBarWidth()
    if (scrollbarWidth) {
        $(document.body).css('padding-right', scrollbarWidth);
        $('.navbar-fixed-top').css('padding-right', scrollbarWidth);    
    }
})
.on('hidden.bs.modal', function () {
    $(document.body).css('padding-right', 0);
    $('.navbar-fixed-top').css('padding-right', 0);
});

function getScrollBarWidth () {
    var inner = document.createElement('p');
    inner.style.width = "100%";
    inner.style.height = "200px";

    var outer = document.createElement('div');
    outer.style.position = "absolute";
    outer.style.top = "0px";
    outer.style.left = "0px";
    outer.style.visibility = "hidden";
    outer.style.width = "200px";
    outer.style.height = "150px";
    outer.style.overflow = "hidden";
    outer.appendChild (inner);

    document.body.appendChild (outer);
    var w1 = inner.offsetWidth;
    outer.style.overflow = 'scroll';
    var w2 = inner.offsetWidth;
    if (w1 == w2) w2 = outer.clientWidth;

    document.body.removeChild (outer);

    return (w1 - w2);
};

Here is the working example: http://jsbin.com/oHiPIJi/64

Agni Pradharma
  • 134
  • 1
  • 6
0

Simply add a class

.modal-open{ padding-right:0px !important;}

it worked for me

Milap
  • 6,915
  • 8
  • 26
  • 46
0

i have faced same problem and following solution works for me

.modal-open {
    overflow: visible;
}
.modal-open, .modal-open .navbar-fixed-top, .modal-open .navbar-fixed-bottom {
    padding-right:0px!important;
}
Vinay Pandya
  • 3,020
  • 2
  • 26
  • 42
0

Try to change all occurence of below

$body.css('padding-right',XXX)

with

$body.css('padding-right'0)

on your bootstrap.js file.

That's All..

Matricore
  • 575
  • 7
  • 12
0

So it turns out I was actually getting right margin of 250px or so. My problem seemed to be that .modal-open was getting set to position: fixed, and that was the cause for whatever reason. So in my case, the fix was similar, but I set the position value to the default as below:

.modal-open{ position: initial !important;}
Raj Baral
  • 661
  • 6
  • 19
zorrotmm
  • 517
  • 2
  • 9
  • 16
0

I fixed my problem and I think it will work for everyone. In bootstrap.js there's a line:

if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)

It means in some case Bootstrap will add a padding-right of scrollbar width while opening a modal. So @pmanOnu was half way right, but don't delete this whole line of code but only

replace bodyPad + this.scrollbarWidth in bootstrap.js with 0

to make Bootstrap adding a padding-right of 0px (which is the same of not adding).

Then add .modal-open {overflow: initial;} to your custom css to prevent Bootstrap from disabling scrollbar while opening modals.

HF Z
  • 11
  • 3
0

If all the above solutions didn't work , it may be because of positioning the content ,Just take a look at the position of the modal

body.modal-open
{
   padding-right: 0 !important; // not important
   position: relative;
}
0

For anyone still struggling with this - the latest version of Bootstrap has a native fix. Just update the bootstrap.min.css and bootstrap.min.js files from the latest version.

http://getbootstrap.com/

0

I really didn't like any of the solutions provided, and used a combination of them (along with a fix I previously had for qTip modals) to come up with something that worked best for me with Bootstrap v3.3.7.

UPDATE: Resolved issue with fixed navbar positioning on iOS.

CSS:

/* fix issue with scrollbars and navbar fixed movement issue with bootstrap modals */
html {
    overflow-y: scroll !important;
}

html.noscroll {
    position: fixed;
    width: 100%;
    top:0;
    left: 0;
    height: 100%;
    overflow-y: scroll !important;
}

.modal-open .modal {
    padding-right: 0 !important;
}

.modal-open[style] {
    padding-right: 0px !important;
}

.modal::-webkit-scrollbar {
    width: 0 !important; /*removes the scrollbar but still scrollable*/
}
/* end modal fix */

JavaScript:

/* fix for modal overlay scrollbar issue */
$(document).ready(function() {
    var curScrollTop;
    var prevScrollTop;
    $('.modal').on('show.bs.modal', function() {
        curScrollTop = $(window).scrollTop();
        $('html').addClass('noscroll').css('top', '-' + curScrollTop + 'px');
        $('.navbar-fixed-top').css({'position':'absolute','top':curScrollTop});     
        $(window).on("resize", function() {             
            var bodyH = $("body").height();
            var winH = $(window).height();
            if (winH > bodyH) {
                prevScrollTop = curScrollTop;
                curScrollTop = 0;
                $('.navbar-fixed-top').css({'position':'absolute','top':'0'}); 
            }
            else {
                $('html').removeClass("noscroll");
                if (curScrollTop == 0) window.scrollTo(0, prevScrollTop);
                else window.scrollTo(0, curScrollTop);
                curScrollTop = $(window).scrollTop(); 
                $('.navbar-fixed-top').css({'position':'absolute','top':curScrollTop});  
                $('html').addClass("noscroll");
            }
            $('html').css('top', '-' + curScrollTop + 'px');
        })
    })
    $('.modal').on('hide.bs.modal', function() {
        $('html').removeClass("noscroll");
         $('.navbar-fixed-top').css({'position':'fixed','top':'0'});
        window.scrollTo(0, curScrollTop);
        $(window).off("resize");
    })
})

This allows the background to be "fixed" yet still allows the modals to be scrollable, resolves the issue of double scrollbar and the repositioning of the fixed navbar.

Note that there is additional code there as well to remember the 'scroll' position (and return to it) when the modal is closed.

Hope this helps anyone else looking to achieve what I was going after.

ouija
  • 186
  • 1
  • 6
-1

I found the answer by Agni Pradharma working for me; however not entirely in Chrome.

It appears the document scrollbar is wider than another elements scrollbar; so I edited the getScrollBarWidth function.

It simply first checks the width; removes the document scrollbar; then compares the difference. It also happens to be much less code.

$(document.body)
    .on('show.bs.modal', function () {
    if (this.clientHeight <= window.innerHeight) {
        return;
    }
    // Get scrollbar width
    var scrollbarWidth = getScrollBarWidth()
    if (scrollbarWidth) {
        $(document.body).css('padding-right', scrollbarWidth);
        $('.navbar-fixed-top').css('padding-right', scrollbarWidth);
    }
})
.on('hidden.bs.modal', function () {
    $(document.body).css('padding-right', 0);
    $('.navbar-fixed-top').css('padding-right', 0);
});

function getScrollBarWidth () {
    var fwidth = $(document).width();
    $('html').css('overflow-y', 'hidden');
    var swidth = $(document).width();
    $("html").css("overflow-y", "visible");
    return (swidth - fwidth);
};
Arie
  • 640
  • 8
  • 16
-1

Here's what I used, will work 100% in Bootstrap 3.2.0 as long as you don't mind forcing scrollbars.

.modal-open .modal {
  overflow-x: hidden;
  overflow-y: scroll;
}
EnergyMud
  • 31
  • 6
-1

the best way is: to add to BODY overflow-y: scroll

and remove 4 function from bootstrap.js -

 checkScrollbar
 setScrollbar
 resetScrollbar
 measureScrollbar
Arpit Srivastava
  • 2,249
  • 1
  • 16
  • 28
kriwec
  • 1
-1

For me it works fine like this

 .modal-open .modal {
  overflow-x: scroll;
  overflow-y: scroll;
}
bummi
  • 27,123
  • 14
  • 62
  • 101
Erduan
  • 1
  • 2
  • 1
-1

For me the following seems to work - tested in Firefox and Chrome on Linux:

body.modal-open {
    overflow: inherit;
    padding-right: inherit !important;
}
-1

This worked for me. Overrides the 17px padding added to the right of the body:

body.modal-open {
    padding-right: inherit !important;
}
PotatoJam
  • 319
  • 1
  • 4
  • 13
-1

I tweaked this answer further up this thread by TBAG

body.modal-open { padding-right: 0px !important; overflow-y: auto; }

With a minor tweak it works on the desktop, for mobile devices overflow is set to hidden

final code

body.modal-open { padding-left: 16px!important; overflow-y: auto; }

Hope this helps!

Community
  • 1
  • 1