Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine responsive modal variations #2130

Closed
winterstetter opened this issue Feb 21, 2012 · 83 comments
Closed

Refine responsive modal variations #2130

winterstetter opened this issue Feb 21, 2012 · 83 comments
Labels
Milestone

Comments

@winterstetter
Copy link

As it says. Thanks for all your love, guys!

@dstroot
Copy link

dstroot commented Mar 6, 2012

I was going to put in something on this very topic but suggest the modal should render at the TOP of a iPhone. I have a long page (when responsively resized for the iPhone) and the modal is rendering at the very bottom so you have to scroll way down to find it. Should render at the top on responsive smaller screens no?

@winterstetter
Copy link
Author

Mark, you"ll figure out the smartest solution. Thanks!

@dstroot
Copy link

dstroot commented Mar 12, 2012

I found that if I had the "fade" option on it rendered the modal at the bottom of my iPhone (bad) but if I turned off the "fade" option it renders at the top (good) so I'm happy - I just won't use fade.

@winterstetter
Copy link
Author

I replicate what @dstroot reports and think it is neither top or bottom the modal should render BUT, if that's technically feasible, where the link for the modal is located on the document. That would be in the center of the visible screen, like on desktop, so no scrolling to top or bottom will be necessary.

@trungpham
Copy link

Has anyone tried the modal on an android phone. It looks completely broken with the top and the bottom getting cut off from the screen.

@mdo mdo mentioned this issue Mar 26, 2012
@ShaneSheppard
Copy link

Is a fix on the way in 2.0.3?

@asoap
Copy link

asoap commented Mar 29, 2012

I'm using 2.0.2 and was having this issue with the iphone. I sorta hacked it together to force it to work.

I forced the backdrop to fill the background by directly setting the height of the black background.

function backdrop( callback ) {
var that = this
, animate = this.$element.hasClass('fade') ? 'fade' : ''

if (this.isShown && this.options.backdrop) {
  var doAnimate = $.support.transition && animate

  this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
    .appendTo(document.body)

  // Edited here:  Set the height of the backdrop
  this.$backdrop.css( 'height', $(document).height() );

I also changed the show function. I overwrote some of the css properties with code, set the position to absolute and margin to 0. Then I manually calculated and set it's centered position.

, show: function () {
    var that = this

    if (this.isShown) return

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

    this.isShown = true
    this.$element.trigger('show')

    // edit here to manually reposition
    this.$element.css('position', 'absolute');
    this.$element.css('margin', 0);
    var new_top = ($(window).height() / 2) - (this.$element.height() / 2) + $(window).scrollTop();
    this.$element.css('top', new_top);          
    var new_left = ($(window).width() / 2) - (this.$element.width() / 2);
    this.$element.css('left', new_left);

I don't know if this is the "proper" way or if it goes against any bootstrap philosophy. But it's doing the trick.

@brightchimp
Copy link

Hi,

Here's the start of a fix. It is only a start as I'm afraid it:
Does not work on android
Is not tested on blackberry
Is not tested on iOS <5

Android issue: If the modal height is greater than the screen, scrolling scrolls the background page, not the modal. The -webkit-overflow-scrolling: touch; line fixes this on iOS 5 but I don't think that is supported in iOS < 5.

My suspicion is that this only works on iOS 5+ so definitely not ready for inclusion but a possible starting point.

Props to @cferdinandi for -webkit-overflow-scrolling in issue #3230 (dupe?).

@media (max-width: 480px) {
  .modal {
    height: 500px; /* Set a default max height of the modal (adjusted later)*/
    position: fixed; /* Display modal in the centre of your screen */
    overflow-y: scroll; /*  Ensure that the modal is scroll-able */
    -webkit-overflow-scrolling: touch; /* Avoid having to use 2 finger scroll on iOS  */
  }
  .modal.fade.in{
    top: 5px; /* Use more screen real estate */
  }
  .modal-body{
    /* Increase the max height of the modal body to try & avoid both it,
     * and the modal container having scroll bars which results in odd behavior */ 
    max-height: 2400px; 
  }  
}

/* Now adjust the height so it handles various screen sizes & orientations */
/* You could make this as granular as you like, or have it more granular at common screen sizes
 * but it should start at the height we set on .modal (i.e. 500px) & work down */
@media (max-width: 480px) and (max-height: 500px){.modal{ height: 450px}}
@media (max-width: 480px) and (max-height: 450px){.modal{ height: 400px}}
@media (max-width: 480px) and (max-height: 400px){.modal{ height: 350px}}
@media (max-width: 480px) and (max-height: 350px){.modal{ height: 300px}}
@media (max-width: 480px) and (max-height: 300px){.modal{ height: 250px}}
@media (max-width: 480px) and (max-height: 250px){.modal{ height: 200px}}
@media (max-width: 480px) and (max-height: 200px){.modal{ height: 150px}}

@tmchow
Copy link

tmchow commented Jul 1, 2012

I was previously having trouble with a modal on a responsive site, but seemed to have solved it with just defining the modal right after the navigation. It now shows at the top where you'd expect it to. Have you tried that?

@cferdinandi
Copy link

@tmchow - Because modals are switched to relative positioning by default in Bootstrap, the issue is not so much that they don't show up at the top of the page, but that they show up at the top of the page even if you're near the bottom, which means the user may not realize there's a modal open. A user shouldn't have to scroll up to view an open modal - it should display wherever they are on the screen.

@brightchimp - any idea why that doesn't work in Android?

@brightchimp
Copy link

@cferdinandi

I'm not entirely sure why exactly but have just had a quick look to remind myself (slow & painful on my old phone).

The problem seems to be what -webkit-overflow-scrolling: touch was introduced to remedy (which Android does not support).

By giving the modal a fixed position, scrolling always scrolls the page in the background, not the contents of the modal. This is not an issue if you don't have much in your modal & it fits nicely on to one screen but if your content takes up more than one screen, anything beyond that is not accessible.

I am also noticing problems with clicking links & generally interacting with controls in the modal.

@gudata
Copy link

gudata commented Jul 5, 2012

Is it nice idea to make the modal respond to classes like .large .small etc?

Currently I need a modal which must be a little bit wider but I can't find "bootstrap way" to resize it.

@desimone
Copy link
Contributor

👍 Attempting to do an Android fix here.

@vviikk
Copy link

vviikk commented Jul 18, 2012

I can't test on anything other than Android Jelly bean at the moment...

but removing top: auto from .modal.fade.in from bootstrap.responsive.css and adding a margin-top:-25% into the main style sheet works for me.

.modal.fade.in {
margin-top: -25%;
top: 50%;
}

@ghost
Copy link

ghost commented Jul 26, 2012

@piggyslasher - Your fix seems to work on iOS 5.1.1 as well.

@iamntz
Copy link

iamntz commented Jul 27, 2012

Hey guys. I had the same issue today and after I failed to make it work with CSS, I picked the hard way: JS!
So instead to reposition the whole modal box, I took another way: what if I just scroll the whole browser window?. So the show method became:

    , show: function () {
        var that = this
          , e = $.Event('show')
        that.oldWindowPosition = $(window).scrollTop(); // 
        $('body, html').scrollTop(0); //

And hide method became:

, hide: function (e) {
        e && e.preventDefault()

        var that = this
        $('body, html').scrollTop(that.oldWindowPosition) //

Lines that have // at the end are those that does the job.

@vviikk
Copy link

vviikk commented Jul 27, 2012

Staicu

So my fix didn't work for you?
On Jul 27, 2012 6:25 PM, "Staicu Ionut" <
reply@reply.github.com>
wrote:

Hey guys. I had the same issue today and after I failed to make it work
with CSS, I picked the hard way: JS!
So instead to reposition the whole modal box, I took another way: what if
I just scroll the whole browser window?. So the show method became:

    , show: function () {
        var that = this
          , e = $.Event('show')
        that.oldWindowPosition = $(window).scrollTop(); //
        $('body, html').scrollTop(0); //

And hide method became:

, hide: function (e) {
        e && e.preventDefault()

        var that = this
        $('body, html').scrollTop(that.oldWindowPosition) //

Lines that have // at the end are those that does the job.


Reply to this email directly or view it on GitHub:
#2130 (comment)

@iamntz
Copy link

iamntz commented Jul 27, 2012

@piggyslasher no, not really. The modal was displayed always on the top of the document. (latest stable iOS)

@grundid
Copy link

grundid commented Aug 1, 2012

It might be interesting to consider a full screen modal on smartphone screens. Since the screen is so small already any additional borders and shadows are simply a waste of valuable space. If you position the modal as fixed it would also reduce the problems with modals not being visible.

@cferdinandi
Copy link

@grundid - That's a splendid recommendation. Shouldn't be too hard to implement, either.

@grundid
Copy link

grundid commented Aug 2, 2012

My current version looks like this:

@media ( max-width : 580px) {
    .modal {
        bottom: 0;
        left: 0;
        position: fixed;
        right: 0;
        top: 0;
        width: auto;
        background-clip: padding-box;
        background-color: #FFFFFF;
        overflow: auto;
        z-index: 1050;
        margin: 0;
        border-radius: 0px;
        border: none;
    }
    .modal-footer {
        background-color: #F5F5F5;
        border-radius: 0 0 6px 6px;
        border-top: 1px solid #DDDDDD;
        bottom: 0;
        box-shadow: 0 1px 0 #FFFFFF inset;
        left: 0;
        margin-bottom: 0;
        padding: 14px 15px 15px;
        position: absolute;
        right: 0;
        text-align: right;
        max-height: 64px;
    }
}

I would like to have the footer always at the bottom, but the above version doesn't work quite well, if the content gets too large. Maybe you have an idea?

@niftylettuce
Copy link

This snippet of jQuery should resolve issues #407, #1017, #1139, #2130, #3361, #3362, #4283 and all other bootstrap mobile modal window resizing issues for the most part!

Gist: Twitter Bootstrap modal responsive fix

// # 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);

@ghost
Copy link

ghost commented Aug 13, 2012

Thanks @niftylettuce ! Works great for me!

@desimone
Copy link
Contributor

Thank you @niftylettuce

On Mon, Aug 13, 2012 at 9:10 AM, matthack notifications@github.com wrote:

Thanks @niftylettuce https://github.com/niftylettuce ! Works great for
me!


Reply to this email directly or view it on GitHubhttps://github.com//issues/2130#issuecomment-7691184.

@jrawlings
Copy link

Thanks @niftylettuce this solves most of our issues. However, it appears modals in landscape mode are still not properly displaying.

This was referenced Aug 18, 2012
@subtubes-io
Copy link

I'm going to play with it some more and look at the code in your fix a bit more. Maybe its the way I am implementing it or something else that is messing with it. Can you tell me if my use is correct.
$.ajax({
url : my_url
type :'POST',
dataType:'JSON',
success :function (data) {
$(''modal_header').html(data.name);
$('.modal-body').html('');
$('#windowTitleDialog').modalResponsiveFix({});
$('#windowTitleDialog').touchScroll();
$('#windowTitleDialog').modal();
}
});

this is the basic code I know I am not caching my variables here, but its just to illustrate the way I am using it.
Maybe I am using the code improperly? Anyways I will investigate it some more and post back tomorrow unless you have some other opinion. BTW on Chrome for Android it really isnt working.

@niftylettuce
Copy link

@orchid1software you are correct, the mobile bug happens for me as well, maybe someone else could have a go at refining this. also we need to add a meta tag in index.html for <meta name="viewport" content="width=device-width,user-scalable=no"> so we can test on mobile easier (we should also test without the viewport tag)

@niftylettuce
Copy link

@orchid1software btw i had said to use v0.0.4 earlier b/c in the YouTube vid it said 0.0.3 on your screen

@niftylettuce
Copy link

@orchid1software also thx for the vid and testing

@subtubes-io
Copy link

@niftylettuce OK I think I found a way to make it work http://www.youtube.com/watch?v=u1PDqNhrUjY&feature=youtu.be Basically you need to be sure ot use a button and not some other clickable item. I documented it here in this vide. Tested it several times and looks awesome. Really neede this to work thanks to Nifty lettuce. I know this is a temp fix but it works quite well as long as you use a button tag.

@deioo
Copy link

deioo commented Sep 20, 2012

For any other tags, use role="button" (e.g Modal link). Also removing the 'fade' class from the modal makes it kind of work on mobile devices. I say 'kind of' because the modal shows, but at a scale of 1/1 of the device, not the viewport.

@chrislovecnm
Copy link

What is the status of this bug? @markdotto is this something you guys are planning on improving? Please :)

@dragonx
Copy link

dragonx commented Oct 13, 2012

I had a bunch of mobile modal bugs sitting on the shelf for a couple months that I was dreading to look at. However, two quick fixes had the modals working satisfactorily for me:

  1. disable fade.

  2. add

    .modal-body { -webkit-overflow-scrolling:touch; }

@jschr
Copy link

jschr commented Oct 13, 2012

Bootstrap's modals also fell a bit short for my purposes as well so I took a crack at extending them. Here's a quick demo page that may be of interest: http://jschr.github.com/bootstrap-modal/

@vviikk
Copy link

vviikk commented Oct 15, 2012

@jschr - you've done it!

And its very very bootstrappy code. I hope this gets merged into the main bootstrap. Great work! Modal FULLY works across all devices. Hope @markdotto can merge this asap.

@desimone
Copy link
Contributor

👊 do it. @markdotto

@tmchow
Copy link

tmchow commented Oct 15, 2012

I've tried this out on Safari on iOS 6 and @jschr's example doesn't fully work for me. When I try to scroll the modal window, it scrolls the pages behind the modal (you can see the page's scrollbar moving).

@jschr
Copy link

jschr commented Oct 15, 2012

@tmchow Ya I haven't been able to figure why the background still scrolls on mobile safari even though I've explicitly set overflow: hidden and position: relative. It's currently a known issue that I'm working on.

@vviikk
Copy link

vviikk commented Oct 17, 2012

@jschr in that case, maybe using touchscroll.js might be worth a shot? or just porting over some code into your js. The scrolling issue on ios was fixed by @niftylettuce using touchscroll.js

@tvb
Copy link

tvb commented Jan 17, 2013

@mdo you really should look into @jschr's code. He pretty close nailed it!
Any thoughts?

@mdo
Copy link
Member

mdo commented Feb 8, 2013

Basically just took care of this today in #6342. Fuck yeah, responsive mobile-first modals! (Still a decent amount to do to make it mo betta, but the basics are all there.)

@mdo mdo closed this as completed Feb 8, 2013
@tvb
Copy link

tvb commented Feb 8, 2013

Thanks :)

@luisjunco-zz
Copy link

I tried quite a few options suggested here and in other issues. None of them worked in older versions of Android and iOS (I'm testing on Android 2.3 and iOS 3.1) with the exception of the solution suggested by @iamntz

Btw, you don't need to override the original methods. Bootstrap exposes the events shown and hidden, so you can just have the following:

$(document).ready(function () {
$('.modal').on('shown', function () {
$(this).data('oldWindowPosition', $(window).scrollTop());
$('body, html').scrollTop(0);
});
$('.modal').on('hidden', function () {
var target = $(this).data('oldWindowPosition');
$('body, html').scrollTop(target);
});
});

@niftylettuce
Copy link

@mdo @jschr nice work guys

@thebarty
Copy link

Hi guys,

I am just starting a new project and wondering: What is the status of using modals in responsive design? Is it safe to use them?

@add1ct3dd
Copy link

I'm also wondering this, there's not brilliant support in 2.3.x, I assume there will be some nice support in 3.0 ?

@cferdinandi
Copy link

For anyone still working through this issue, I ended up just writing my own modal script instead: http://cferdinandi.github.io/modals/

Where Bootstrap struggles with this is around the absolute positioning coupled with overflow content (and the sometimes it works/sometimes it doesn't scrolling of that content). The script I wrote uses fixed positioning instead. Modals are automatically positioned based on where the user is on the screen, and when they scroll, the modal moves, too. This allows you to use a modal that expands vertically to accomodate more content, getting around the "scrolling inside the modal sucks on mobile devices" issue.

@lookfirst
Copy link
Contributor

@cferdinandi I don't see how this is any better than the @jschr code. No animations and the modal seems pinned to the top of the window instead of centering on the screen. I'm all for new implementations, but I'd hope they'd be an advancement over existing solutions.

@cferdinandi
Copy link

@lookfirst - Sorry, I haven't been paying close attention to this thread in a while, so I didn't take a look at @jschr's work. Apologies for the redundancy.

@twbs twbs locked and limited conversation to collaborators Jun 14, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests