53

I have a page with a modal with a lot of info so you need to scroll. This modal contains a link to a second modal.

When I

  • open modal 1
  • click on link to open modal 2 (modal 1 stays in background)
  • and then close modal 2 so that I am back on modal 1

modal 1 looses scrolling (there is still a scroll bar but it doesn't do anything). Instead the modal stays in the position it was at the time of opening modal 2.

I played around with closing the background modal with js first (but that messes up scrolling on the second modal). It appears that every time I try to open/close more than one modal I always get some issue with the scrolling.

Any suggestions on how to handle this?

gpanterov
  • 1,365
  • 2
  • 15
  • 25

6 Answers6

69

Add

.modal { overflow: auto !important; }

To your CCS.

Without your code I went ahead and created this jsFiddle that recreates your issue, or at least a very similar one. Add your code and I will test if this works or not.

Adding that line to the CSS fixed the issue as demonstrated with this jsFiddle.

Solution taken from this thread on github which offers other solutions as well.

Keeleon
  • 1,352
  • 11
  • 14
  • 2
    This fixed it! The only, somewhat minor issue with it appears to be that after you close the second modal, a second scroll bar becomes visible (seems to be from the main page). (Unfortunately the code is too big to post here...) – gpanterov Apr 07 '16 at 01:09
  • 1
    The solutions provided by Ahsan Khan / Abir.d don't have the second scroll bar bug. – MarijnK May 14 '19 at 06:43
  • 1
    Perfect solution, simply and effective. Thanks. – Sylar Oct 14 '19 at 15:37
  • 2
    Can someone explain though why the problem exists in the first place? Ie why does the first modal lose scrollability? – Notaras Apr 09 '20 at 07:05
  • this is not the right solution. Not it shows two scrolls.. one for the modal and another for the background content. – MohamedSanaulla Nov 22 '22 at 09:33
39

The solution that worked for me was:

$('.modal').on("hidden.bs.modal", function (e) { 
    if ($('.modal:visible').length) { 
        $('body').addClass('modal-open');
    }
});
Abir.d
  • 718
  • 6
  • 11
  • 4
    Better to use `'body'` selector isntead of `'.modal'` because modals usually dynamically created. In this case this code snippet can be executed once on start and all modals should be fine then. – Ruslan Stelmachenko Sep 06 '18 at 08:55
  • 2
    Solution apported by @ahsan-khan (https://stackoverflow.com/a/55162846/1170950) is better because also works for dynamically generated modals. – kpull1 Apr 09 '19 at 08:49
  • 1
    kpull1 this solution avoids the bug where the page's scrollbar shows as a second scrollbar as with ahsan-khan's solution. – MarijnK May 14 '19 at 06:41
29
   $(document).on('hidden.bs.modal', '.modal', function () {
        $('.modal:visible').length && $(document.body).addClass('modal-open');
   });
Ahsan Khan
  • 678
  • 9
  • 12
  • 2
    it's better to explain why this snippet solves the problem – JimHawkins Mar 14 '19 at 14:41
  • 2
    basically default bootstrap modal depends on "modal-open" class in the html body element (when a modal is opened). If we use multiple BS modal using ajax, we can mess with removing "modal-open" class when there are other visible modal need to use the selector. So need to track visible modal; only remove the "modal-open" when there is no visible one. This github link also handle backdrop z-index https://github.com/nakupanda/bootstrap3-dialog/issues/70#issuecomment-132361422 If we only fix the css without tracking visible modal with js. the layer below modal is scrollable, not good for mobile – kite Nov 02 '20 at 23:01
  • I use ajax loading spinner using bootstrap modal globally for all ajax request, so $('.modal:visible').length is not accurate, I have to use global counter to count/track opened modal. and add the 'modal-open' class to body if the opened modal counter is not 0 – kite Nov 03 '20 at 10:32
  • 2
    This is better answer :) – STA Jul 30 '21 at 05:43
  • Or bind that event in the modal initialization to the modal that is stacked over others. Might be less intrusive. – Dr. Hans-Peter Störr Jul 17 '23 at 13:36
6

this is the solution:

<script>
    $('#id_ofyou_secondary_modal').on('hidden.bs.modal', function (e) {

      $('body').addClass('modal-open');

    });
</script>

take care that "#idofyousecondarymodal" is the id of the secondary or tertiary or infinite modal. but NEVER write the ID of the first modal.

example i have 2 modal:

<div id="mymodal1" class="modal fade in" style="display:none;">
.
.
.
.
</div>
<div id="mymodal2" class="modal fade in" style="display:none;">
.
.
.
.
</div>   

then the script will be:

<script>
    $('#mymodal2').on('hidden.bs.modal', function (e) {

      $('body').addClass('modal-open');

    });
</script>

jus add this code and work fine.

3

I tried the previous solutions, and not working for my use case:

  1. just adding css .modal { overflow: auto !important; } This will cause the content below modal become scrollable. Not good when you want to keep the previous content position. especially in mobile browser.
  2. Use javascript to track opened modal and keep the 'modal-open' class in body element using this jQuery selector $('.modal:visible').length. This is not working when there are multiple modal opened and closed fast. I use BS modal for my ajax spinner, so the $('.modal:visible') is not accurate.

This is the working one for me:

  1. Use JS global variable to keep track/count of opened modal; instead of just using :visible selector
  2. And I added css style so I don't have to recalculate backdrop z-index https://stackoverflow.com/a/63473738/423356

var bootstrapModalCounter = 0; //counter is better then using visible selector

    $(document).ready(function () {  
      $('.modal').on("hidden.bs.modal", function (e) {
        --bootstrapModalCounter;
        if (bootstrapModalCounter > 0) {
          //don't need to recalculate backdrop z-index; already handled by css
          //$('.modal-backdrop').first().css('z-index', parseInt($('.modal:visible').last().css('z-index')) - 10);
          $('body').addClass('modal-open');
        }
      }).on("show.bs.modal", function (e) {
        ++bootstrapModalCounter;
        //don't need to recalculate backdrop z-index; already handled by css
      });
    });
.modal { 
/*simple fix for multiple bootstrap modal backdrop issue: 
don't need to recalculate backdrop z-index;
https://stackoverflow.com/questions/19305821/multiple-modals-overlay/21816777 */
  background: rgba(0, 0, 0, 0.5);
}

This is modified fiddle from @Keeleon for the fix https://jsfiddle.net/4m68uys7/

This is github issue https://github.com/nakupanda/bootstrap3-dialog/issues/70

kite
  • 1,478
  • 1
  • 15
  • 27
1

Add following to your CSS :

.modal
{
  overflow: scroll !important;
}
Sreenath S
  • 669
  • 6
  • 9