adamsmith
adamsmith

Reputation: 5999

Bootstrap modal has a flaw

As I was learning bootstrap and trying out the example on the official page, I found a flaw (maybe) with the modal component.

Click the "Launch demo modal", you will notice there is a notable margin on the top right corner, and the navbar will stretch/shrink when the modal dialog disappear/appear.

Is that a bug or intentional? I think it's annoying, How to disable it?

Upvotes: 5

Views: 7307

Answers (9)

Rachid O
Rachid O

Reputation: 14002

this is the best solution i found:

body.modal-open, .modal-open .navbar-fixed-top, .modal-open .navbar-fixed-bottom {
    padding-right: 0px !important;
    overflow-y: auto;
}

Upvotes: 5

sanjay govind
sanjay govind

Reputation: 1

I tried Agni Pradharma's fix, but had to slightly tweak it to make it work.

I got it working using this:

 $(document.body)
    .on('show.bs.modal', function () {
        if (this.clientHeight <= window.innerHeight) {
            return;
        }
        // Get scrollbar width
        var scrollbarWidth = getScrollBarWidth()
        if (scrollbarWidth) {
            $('.navbar-fixed-top').css('margin-right', scrollbarWidth);    
        }
    })
    .on('hide.bs.modal', function () {
        $('.navbar-fixed-top').css('margin-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);
    };

Upvotes: 0

Dre
Dre

Reputation: 1

margin-right did not work in my case, I found padding-right to solve the issue.

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

Upvotes: 0

ClaraG
ClaraG

Reputation: 342

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

this worked for me

Upvotes: 0

Jay Mathis
Jay Mathis

Reputation: 1165

Be sure to test for both when the original page already has a scrollbar and does not already have a scrollbar.

This worked for me with v3.1.1.

html, .modal, .modal.in, .modal-backdrop.in {
    overflow-y: auto;
}

Upvotes: 2

Paul Cochrane
Paul Cochrane

Reputation: 399

I had this issue as well (bootstrap 3.1.1). I was opening a modal and there was a missing space on the backdrop (where a scroll bar will appear if the modal is greater than page height) and the content of the page was resizing and shifting to the left.

My layout uses a fixed navbar.

I added a couple of CSS selectors that seems to prevent the page resizing and ensuring that the modal-backdrop fills the screen

html {
    /* This prevents the page from shifting when a modal is opened e.g. search */
    overflow-y: auto;   
}
.modal,.modal.in,.modal-backdrop.in {
    /* These are to prevent the blank space for the scroll bar being displayed unless the modal is > page height */
    overflow-y: auto;
}

I still find it a bit odd where you can have two scroll bars if the page and the modal content is more than the screen height but I can live with that.

Upvotes: 1

Agni Pradharma
Agni Pradharma

Reputation: 134

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

Upvotes: 3

Helen Marie
Helen Marie

Reputation: 21

in addition to this also make sure you have the following

html { overflow-y:auto; }

in your stylesheet to stop it shifting left

Upvotes: 1

lilasquared
lilasquared

Reputation: 138

To fix this manually simply add

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

to a stylesheet that is applied after the bootstrap stylesheets.

If you want to hide the scrollbar as well you can add

.modal
{
    overflow-y: auto;
}

as well.

Upvotes: 7

Related Questions