Twitter Bootstrap modal on mobile devices

103,135

Solution 1

EDIT: An unofficial Bootstrap Modal modification has been built to address responsive/mobile issues. This is perhaps the simplest and easiest way to remedy the problem.

There has since been a fix found in one of the issues you discussed earlier

in bootstrap-responsive.css

.modal { 
    position: fixed; 
    top: 3%; 
    right: 3%; 
    left: 3%; 
    width: auto; 
    margin: 0; 
}
.modal-body { 
    height: 60%; 
}

and in bootstrap.css

.modal-body { 
    max-height: 350px; 
    padding: 15px; 
    overflow-y: auto; 
    -webkit-overflow-scrolling: touch; 
 }

Solution 2

Gil's answer holds promise (the library he linked to) --- but for the time being, it still doesn't work when scrolled down on the mobile device.

I solved the issue for myself using just a snippet of CSS at the end of my CSS files:

@media (max-width: 767px) {
  #content .modal.fade.in {
    top: 5%;
  }
}

The #content selector is simply an id that wraps my html so I can override Bootstrap's specificity (set to your own id wrapping your modal html).

The downside: It's not centered vertically on the mobile devices.

The upside: It's visible, and on smaller devices, a reasonably sized modal will take up much of the screen, so the "non-centering" won't be as apparent.

Why it works:

When you're at low screen sizes with Bootstrap's responsive CSS, for devices with smaller screens, it sets .modal.fade.in's 'top' to 'auto'. For some reason the mobile webkit browsers seem to have a hard time with figuring out the vertical placement with the "auto" assignment. So just switch it back to a fixed value and it works great.

Since the modal is already set to postition: absolute, the value is relative to the viewport's height, not the document height, so it works no matter how long the page is or where you're scrolled to.

Solution 3

The solution by niftylettuce in issue 2130 seems to fix modals in all mobile platforms...

9/1/12 UPDATE: The fix has been updated here: twitter bootstrap jquery plugins

(the code below is older but still works)

// # Twitter Bootstrap modal responsive fix by @niftylettuce
//  * resolves #407, #1017, #1339, #2130, #3361, #3362, #4283
//   <https://github.com/twitter/bootstrap/issues/2130>
//  * built-in support for fullscreen Bootstrap Image Gallery
//    <https://github.com/blueimp/Bootstrap-Image-Gallery>

// **NOTE:** If you are using .modal-fullscreen, you will need
//  to add the following CSS to `bootstrap-image-gallery.css`:
//
//  @media (max-width: 480px) {
//    .modal-fullscreen {
//      left: 0 !important;
//      right: 0 !important;
//      margin-top: 0 !important;
//      margin-left: 0 !important;
//    }
//  }
//

var adjustModal = function($modal) {
  var top;
  if ($(window).width() <= 480) {
    if ($modal.hasClass('modal-fullscreen')) {
      if ($modal.height() >= $(window).height()) {
        top = $(window).scrollTop();
      } else {
        top = $(window).scrollTop() + ($(window).height() - $modal.height()) / 2;
      }
    } else if ($modal.height() >= $(window).height() - 10) {
      top = $(window).scrollTop() + 10;
    } else {
      top = $(window).scrollTop() + ($(window).height() - $modal.height()) / 2;
    }
  } else {
    top = '50%';
    if ($modal.hasClass('modal-fullscreen')) {
      $modal.stop().animate({
          marginTop  : -($modal.outerHeight() / 2)
        , marginLeft : -($modal.outerWidth() / 2)
        , top        : top
      }, "fast");
      return;
    }
  }
  $modal.stop().animate({ 'top': top }, "fast");
};

var show = function() {
  var $modal = $(this);
  adjustModal($modal);
};

var checkShow = function() {
  $('.modal').each(function() {
    var $modal = $(this);
    if ($modal.css('display') !== 'block') return;
    adjustModal($modal);
  });
};

var modalWindowResize = function() {
  $('.modal').not('.modal-gallery').on('show', show);
  $('.modal-gallery').on('displayed', show);
  checkShow();
};

$(modalWindowResize);
$(window).resize(modalWindowResize);
$(window).scroll(checkShow);

Solution 4

We use this code to center the Bootstrap modal dialogs when they open. I haven't had any issue with them on iOS while using this but I'm not sure if it will work for Android.

$('.modal').on('show', function(e) {
    var modal = $(this);
    modal.css('margin-top', (modal.outerHeight() / 2) * -1)
         .css('margin-left', (modal.outerWidth() / 2) * -1);
    return this;
});

Solution 5

Admittedly, I haven't tried any of the solutions listed above but I was (eventually) jumping for joy when I tried jschr's Bootstrap-modal project in Bootstrap 3 (linked to in the top answer). The js was giving me trouble so I abandoned it (maybe mine was a unique issue or it works fine for Bootstrap 2) but the CSS files on their own seem to do the trick in Android's native 2.3.4 browser.

In my case, I've resorted so far to using (sub-optimal) user-agent detection before using the overrides to allow expected behaviour in modern phones.

For example, if you wanted all Android phones ver 3.x and below only to use the full set of hacks you could add a class "oldPhoneModalNeeded" to the body after user agent detection using javascript and then modify jschr's Bootstrap-modal CSS properties to always have .oldPhoneModalNeeded as an ancestor.

Share:
103,135
ty.
Author by

ty.

Hi, I'm Ian. Here's my homepage: https://www.ianww.com/

Updated on July 05, 2022

Comments

  • ty.
    ty. almost 2 years

    Bootstrap modals don't work correctly on Android and iOS. The issue tracker acknowledges the problem but does not offer a working solution:

    Modals in 2.0 are broken on mobile.

    Modal window in 2.0 not positioning properly

    The screen darkens but the modal itself is not visible in the viewport. It's possible to find it at the top of the page. The problem occurs when you've scrolled down on the page.

    Here is a relevant portion of bootstrap-responsive.css:

    .modal {
        position:fixed;
        top:50%;
        left:50%;
        z-index:1050;
        max-height:500px;
        overflow:auto;
        width:560px;
        background-color:#fff;
        border:1px solid #999;
        -webkit-border-radius:6px;
        -moz-border-radius:6px;
        border-radius:6px;
        -webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);
        -moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);
        box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);
        -webkit-background-clip:padding-box;
        -moz-background-clip:padding-box;
        background-clip:padding-box;
        margin:-250px 0 0 -280px;
    }
    

    Is there a fix I can apply?

  • Icarus
    Icarus over 11 years
    Fixed the issue for me on an iPhone with ios 6 (whatever version of Safari that is)
  • Martin Booka Weser
    Martin Booka Weser over 11 years
    there is a mistake in .modal. You have top: 3% and bottom: 3%. If you remove the bottom: 3% it is working as expected.
  • acconrad
    acconrad over 11 years
    FYI @Maurice I updated the answer to reflect on a new Github project that solves this problem in a more elegant solution.
  • martar
    martar over 8 years
    I found it necessary to also add bottom: 3%; in the mobile css version in the .modal class so that on the mobile , it is possible to scroll to the very end of the modal. Also be carefull with max-height for desktop verison. TO avoid in the desktop version, that the body of the modal is very small, and footer of the modal is on the main scree, I added max-height to 1200 px;