featherlight icon indicating copy to clipboard operation
featherlight copied to clipboard

[feature request] Prevent scrolling on html/body

Open corysimmons opened this issue 7 years ago • 13 comments

When modals are expanded, it's nice if the html/body isn't able to scroll.

You can achieve this by applying overflow: hidden to both.

Need to be mindful that content can expand vertically further than screen so overflow-y: auto would need to be added to the lightbox container.

corysimmons avatar Dec 20 '16 17:12 corysimmons

What would be the impact on #77?

marcandre avatar Dec 20 '16 18:12 marcandre

I don't think the html, body {overflow: hidden} styles would cascade to the <iframe> if it was on a different origin.

I'm too lazy to check if it'd affect it on same origin. If it did, maybe this would work:

html,
body {
  overflow: hidden; // disable for local viewport
}

html html {
  overflow: auto; // enable for child viewport
}

Bootstrap, and 99% of other modal frameworks do this. Locking the viewport is pretty standard with modals.

corysimmons avatar Dec 21 '16 01:12 corysimmons

I'm not fully understanding the comments here as I'm not very advanced. That said, I have an example for you of inappropriate scrolling of the underlying page when the user is scrolling in the lightbox. It's on this page. First make sure that your window height is not so huge that scrolling is not necessary to see the bottom of that page. Then, in the sticky footer, click on [Terms of Use].

The deal is that if you keep the cursor inside the Terms of Use box at all times and use the mouse scroll wheel to get to the bottom, all will go well, but... if you keep scrolling a bit more, as if to scroll an inch or more past the end of the box, the underlying page starts to scroll. This also happens in the other direction. In both cases the underlying page must of course not already be scrolled to the end in order for this to be observed.

The comments about overflow don't seem to me to be relevant to what I'm demonstrating, but I'm not utterly sure. Is this a Featherlight bug? Or is it me?

The box is no iframe but is loaded with ordinary HTML, via <a href="#" data-featherlight="url_to_django_script_that_returns_html">.

michaelcoconnor avatar Jan 28 '17 07:01 michaelcoconnor

After some consideration, I tend to agree with the request.

@corysimmons Is there a need to add overflow: hidden to the body in addition to the <html>?

marcandre avatar Jan 28 '17 12:01 marcandre

Also, the close button should probably not be scrolling. Is there a simple way to achieve that though?

marcandre avatar Jan 28 '17 12:01 marcandre

Latest version should not scroll globally. Would still be nice to have the close box not scrolling either.

marcandre avatar Feb 20 '17 19:02 marcandre

I have just now installed 1.7.1 on the site to which I provided a link above, and I'm seeing the same scrolling behavior.

michaelcoconnor avatar Feb 20 '17 21:02 michaelcoconnor

@marcandre regarding your statement:

Latest version should not scroll globally.

Can you explain what you mean by latest version? I'm still seeing a separate "scroll" branch where this was fixed but never merged to master for inclusion in a release. I just looked at 1.7.7 and it doesn't contain the code from the scroll branch:

https://github.com/noelboss/featherlight/compare/scroll

Were you waiting for a fix of the close box scrolling you mentioned above to work this into a release?

jameswilson avatar Aug 07 '17 22:08 jameswilson

Oh :blush:, sorry, indeed the changes never made it to master.

1.7.8 released.

marcandre avatar Aug 08 '17 17:08 marcandre

Mil Merci! @marcandre

jameswilson avatar Aug 08 '17 22:08 jameswilson

I've done some cross-browser and device testing of this solution and found that it does not work on iOS, because mobile safari does not respect overflow: hidden on the html element as a way to prevent scrolling. The workaround requires also setting position: fixed on the body tag, and then a small piece of javascript to fix the scroll position in place and prevent that slinky top/bottom edge effect as you drag/scroll with your finger on touch devices.

Here is a workaround that can be used inside my application's script:

  $.featherlight.defaults.beforeOpen = function() {
    // Lock the scroll position in place on the body with 'position:fixed' and negative top margin.
    $(document.body).css({
      'top':  '-' + $(document.body).scrollTop() + 'px',
      'position': 'fixed',
      'width': '100%', // ensure page width unaffected by fixed position.
      'height': 'inherit' // note height of 100% on body breaks ios
    });
  };

  $.featherlight.defaults.afterClose = function() {
    // Unset the scroll position on the body.
    var top = Math.abs(parseInt($(document.body).css('top')));
    $(document.body).css({
      'top': '',  // Empty value removes the CSS rule from the inline style attribute.
      'position': '',
      'width': '',
      'height': ''
    });
    // Move viewport back to the original position which was lost when body was
    // locked with 'position: fixed'.
    window.scrollTo(0, top);
  }

I'll submit a PR momentarily containing this solution rewritten as something that will work generically.

Thanks.

jameswilson avatar Aug 14 '17 22:08 jameswilson

@marcandre is there any reason not to overwrite the close button position to fixed in our own css? This does the job with the close button for me, to avoid it scrolling out of view.

Edit - I see this wouldnt necessarily work if the modal isn't the size of the window.

pandalion avatar Feb 08 '18 11:02 pandalion

@jameswilson thanks a lot for this solution.

If you want the to work across browsers —chrome V 60+ does not work in the original— this small change will do the trick >

'top': '-' + window.scrollY + 'px',

instead of

'top': '-' + $(document.body).scrollTop() + 'px',

I tested the change in Safari, Chrome and Firefox

  $.featherlight.defaults.beforeOpen = function() {
    // Lock the scroll position in place on the body with 'position:fixed' and negative top margin.
    var topOriginal = Math.abs(parseInt($(document.body).css('top')));
    $(document.body).css({
      'top':  '-' + window.scrollY  + 'px',
      'position': 'fixed',
      'width': '100%', // ensure page width unaffected by fixed position.
      'height': 'inherit' // note height of 100% on body breaks ios
    });
  };

  $.featherlight.defaults.afterClose = function() {
    // Unset the scroll position on the body.
    var top = Math.abs(parseInt($(document.body).css('top')));
    $(document.body).css({
      'top': '',  // Empty value removes the CSS rule from the inline style attribute.
      'position': '',
      'width': '',
      'height': ''
    });
    // Move viewport back to the original position which was lost when body was
    // locked with 'position: fixed'.
    window.scrollTo(0, top);
  }

ganar avatar Mar 06 '18 18:03 ganar