[css] How to enable scrolling of content inside a modal?

I'm trying to fit a lot of text into a modal box created using Twitter Bootstrap, but I'm having a problem: that content refuses to scroll.

I tried adding overflow:scroll and overflow-y:scroll, but to no avail; that merely causes it to display a scroll bar without actually enabling the scrolling.

What's the cause behind that and what can I do?

This question is related to css twitter-bootstrap scroll

The answer is


Bootstrap will add or remove a css "modal-open" to the <body> tag when we open or close a modal. So if you open multiple modal and then close arbitrary one, the modal-open css will be removed from the body tag.

But the scroll effect depend on the attribute "overflow-y: auto;" defined in modal-open


This answer actually has two parts, a UX warning, and an actual solution.

UX Warning

If your modal contains so much that it needs to scroll, ask yourself if you should be using a modal at all. The size of the bootstrap modal by default is a pretty good constraint on how much visual information should fit. Depending on what you're making, you may instead want to opt for a new page or a wizard.

Actual Solution

Is here: http://jsfiddle.net/ajkochanowicz/YDjsE/2/

This solution will also allow you to change the height of .modal and have the .modal-body take up the remaining space with a vertical scrollbar if necessary.

UPDATE

Note that in Bootstrap 3, the modal has been refactored to better handle overflowing content. You'll be able to scroll the modal itself up and down as it flows under the viewport.


I'm having this issue on Mobile Safari on my iPhone6

Bootstrap adds the class .modal-open to the body when a modal is opened.

I've tried to make minimal overrides to Bootstrap 3.2.0, and came up with the following:

.modal-open {
    position: fixed;
}

.modal {
    overflow-y: auto;
}

For comparison, I've included the associated Bootstrap styles below.

Selected extract from bootstrap/less/modals.less (don't include this in your fix):

// Kill the scroll on the body
.modal-open {
  overflow: hidden;
}

// Container that the modal scrolls within
.modal {
  display: none;
  overflow: hidden;
  position: fixed;
  -webkit-overflow-scrolling: touch;
}

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

Mobile Safari version used: User-Agent Mozilla/5.0 (iPhone; CPU iPhone OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B411 Safari/600.1.4


.modal-body {
    max-height: 80vh;
    overflow-y: scroll;
}

it's works for me


If I recall correctly, setting overflow:hidden on the body didn't work on all the browsers I was testing for a modal library I built for a mobile site. Specifically, I had trouble with preventing the body from scrolling in addition to the modal scrolling even when I put overflow:hidden on the body.

For my current site, I ended up doing something like this. It basically just stores your current scroll position in addition to setting "overflow" to "hidden" on the page body, then restores the scroll position after the modal closes. There's a condition in there for when another bootstrap modal opens while one is already active. Otherwise, the rest of the code should be self explanatory. Note that if the overflow:hidden on the body doesn't prevent the window from scrolling for a given browser, this at least sets the original scroll location back upon exit.

function bindBootstrapModalEvents() {
    var $body = $('body'),
        curPos = 0,
        isOpened = false,
        isOpenedTwice = false;
    $body.off('shown.bs.modal hidden.bs.modal', '.modal');
    $body.on('shown.bs.modal', '.modal', function () {
        if (isOpened) {
            isOpenedTwice = true;
        } else {
            isOpened = true;
            curPos = $(window).scrollTop();
            $body.css('overflow', 'hidden');
        }
    });
    $body.on('hidden.bs.modal', '.modal', function () {
        if (!isOpenedTwice) {
            $(window).scrollTop(curPos);
            $body.css('overflow', 'visible');
            isOpened = false;
        }
        isOpenedTwice = false;
    });
}

If you don't like this, the other option would be to assign a max-height and overflow:auto to .modal-body like so:

.modal-body {
  max-height:300px;
  overflow:auto;
}

For this case, you could configure the max-height for different screen sizes and leave the overflow:auto for different screen sizes. You would have to make sure that the modal header, footer, and body don't add up to more than the screen size, though, so I would include that part in your calculations.


I was able to overcome this by using the "vh" metric with max-height on the .modal-body element. 70vh looked about right for my uses.

.modal-body {
   overflow-y: auto;
   max-height: 70vh;
}

I had the same issue, and found a fix as below:

$('.yourModalClassOr#ID').on('shown.bs.modal', function (e) {
    $(' yourModalClassOr#ID ').css("max-height", $(window).height());
    $(' yourModalClassOr#ID ').css("overflow-y", "scroll");          /*Important*/
    $(' yourModalClassOr#ID ').modal('handleUpdate');

});

100% working.


Actually for Bootstrap 3 you also need to override the .modal-open class on body.

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

When using Bootstrap modal with skrollr, the modal will become not scrollable.

Problem fixed with stop the touch event from propagating.

$('#modalFooter').on('touchstart touchmove touchend', function(e) {
    e.stopPropagation();
});

more details at Add scroll event to the element inside #skrollr-body


In Bootstrap 3 you have to change the css class .modal

before (bootstrap default) :

.modal {

    overflow-y: auto;
}

after (after you edit it):

.modal {

    overflow-y: scroll;
}

After using all these mentioned solution, i was still not able to scroll using mouse scroll, keyboard up/down button were working for scrolling content.

So i have added below css fixes to make it working

.modal-open {
    overflow: hidden;
}

.modal-open .modal {
    overflow-x: hidden;
    overflow-y: auto;
    **pointer-events: auto;**
}

Added pointer-events: auto; to make it mouse scrollable.


Set height for modal-body and not for the whole modal to get a perfect scroll on modal overlay. I get it work like this:

.MyModal {
    height: 450px;
    overflow-y: auto;
}

Here you can set height as per your requirements.


This is how I did it purely with CSS overriding some classes:

.modal {
  height: 60%;

  .modal-body {
    height: 80%;
    overflow-y: scroll;
  }
}

Hope it helps you.


In Bootstrap.css change the background attribute (position) of Modal from fixed to absolute


Solution 1: You can declare .modal{ overflow-y:auto} or .modal-open .modal{ overflow-y:auto} if you are using below 3v of bootstrap (for upper versions it is already declared).

Bootstrap adds modal-open class to body in order to remove scrollbars in case modal is shown, but does not add any class to html which also can have scrollbars, as a result the scrollbar of html sometimes can be visible too, to remove it you have to set modal show/hide events and add/remove overflow:hidden on html. Here how to do this.

$('.modal').on('hidden.bs.modal', function () {
   $('html').css('overflow','auto');
}).on('shown.bs.modal', function () {
   $('html').css('overflow','hidden');
});

Solution 2: As modal has functionality keys, the best way to handle this is to fix height of or even better connect the height of modal with height of the viewport like this -

.modal-body {
     overflow:auto; 
     max-height: 65vh;
}

With this method you also do not have to handle body and html scrollbars.

Note 1: Browser support for vh units.

Note 2: As it is proposed above. If you change .modal{position:fixed} to .modal{position:absolute}, but in case page has more height than modal user can scroll too much up and modal will disappear from viewport, this is not good for user experience.


Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to twitter-bootstrap

Bootstrap 4: responsive sidebar menu to top navbar CSS class for pointer cursor How to install popper.js with Bootstrap 4? Change arrow colors in Bootstraps carousel Search input with an icon Bootstrap 4 bootstrap 4 responsive utilities visible / hidden xs sm lg not working bootstrap.min.js:6 Uncaught Error: Bootstrap dropdown require Popper.js Bootstrap 4 - Inline List? Bootstrap 4, how to make a col have a height of 100%? Bootstrap 4: Multilevel Dropdown Inside Navigation

Examples related to scroll

How to window.scrollTo() with a smooth effect Angular 2 Scroll to bottom (Chat style) Scroll to the top of the page after render in react.js Get div's offsetTop positions in React RecyclerView - How to smooth scroll to top of item on a certain position? Detecting scroll direction How to disable RecyclerView scrolling? How can I scroll a div to be visible in ReactJS? Make a nav bar stick Disable Scrolling on Body