Bug 153852 - <body> with overflow:hidden CSS is scrollable on iOS
Summary: <body> with overflow:hidden CSS is scrollable on iOS
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: CSS (show other bugs)
Version: WebKit Nightly Build
Hardware: iPhone / iPad iOS 10
: P2 Normal
Assignee: Nobody
URL: https://github.com/w3c/csswg-drafts/c...
Keywords: HasReduction, InRadar
Depends on:
Blocks: 159753
  Show dependency treegraph
 
Reported: 2016-02-03 18:58 PST by Chris Rebert
Modified: 2019-07-21 21:51 PDT (History)
27 users (show)

See Also:


Attachments
Testcase demonstrating the problem (8.37 KB, text/html)
2016-02-03 18:58 PST, Chris Rebert
no flags Details
GIF video demonstrating the bug (885.72 KB, image/gif)
2016-02-04 01:38 PST, Chris Rebert
no flags Details
patch (16.67 KB, patch)
2019-05-06 10:15 PDT, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (16.78 KB, patch)
2019-05-06 10:43 PDT, Antti Koivisto
ews: commit-queue-
Details | Formatted Diff | Diff
Archive of layout-test-results from ews215 for win-future (13.53 MB, application/zip)
2019-05-07 02:42 PDT, Build Bot
no flags Details
patch (14.08 KB, patch)
2019-05-07 03:11 PDT, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (11.56 KB, patch)
2019-05-07 03:20 PDT, Antti Koivisto
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Rebert 2016-02-03 18:58:32 PST
Created attachment 270621 [details]
Testcase demonstrating the problem

Applying `overflow: hidden` to the `<body>` should make it non-scrollable.
This works correctly on OS X Safari, but doesn't work correctly on iOS Safari.

Original Bootstrap issue:
Lost to the sands of time, but https://github.com/twbs/bootstrap/issues/14839 is relevant & popular.
See also http://getbootstrap.com/getting-started/#overflow-and-scrolling

Steps to reproduce:
1. Open the attached testcase in iOS Safari.
2. Tap the "Launch demo modal" button.
3. A yellow box with text appears.
4. Scroll the yellow box to its bottom, where there are "Close" and "Save changes" buttons, and lift your finger off the screen to ensure that the scroll gesture ends.
5. Attempt to scroll the yellow box further downward (which is to say, apply a "fling upward" gesture to the yellow box).

Actual result:
The <body> underneath the yellow box scrolls downward.

Expected result:
The <body> should not scroll (just like on OS X Safari).
Comment 1 Chris Rebert 2016-02-04 01:38:35 PST
Created attachment 270644 [details]
GIF video demonstrating the bug
Comment 2 Simon Fraser (smfr) 2016-03-22 16:15:42 PDT
I would be concerned about changing behavior here, because it would cause content which has been reachable on earlier iOS versions to become unreachable.
Comment 3 Chris Rebert 2016-03-22 17:21:11 PDT
Android Chrome already made the behavior change and blazed the trail here:
https://bugs.chromium.org/p/chromium/issues/detail?id=175502

They tracked broken sites in https://bugs.chromium.org/p/chromium/issues/detail?id=444581 (and its dupes).
They communicated with several sites and got some to fix their CSS.

In comments 24-25 & 28, they acknowledge some breakage, but don't think there's enough of it to justify switching back:
https://bugs.chromium.org/p/chromium/issues/detail?id=444581#c24
https://bugs.chromium.org/p/chromium/issues/detail?id=444581#c28

I couldn't find any signs of any subsequent revert.

----

If WebKit were to disagree with Chrome's analysis and fear too much breakage,
what would be the path forward?
A new "yes, I really truly want 'hidden' here!" value for the CSS 'overflow' property?
Comment 4 Eric Allam 2016-07-12 04:42:00 PDT
This bug has recently become a problem for a project I'm working on where we are trying to implement a chat interface, with a header element that acts like a navigation bar, and a footer element that includes a text field, with a chat container which includes the chat messages that should be able to scroll. I know this isn't a reduced test case but we have put together a stripped down version of the chat on JSBin which demonstrates this problem too:

http://jsbin.com/ruyito/edit?html,css,output
Comment 5 Chris Rebert 2016-12-04 21:54:42 PST
(In reply to comment #2)
> I would be concerned about changing behavior here, because it would cause
> content which has been reachable on earlier iOS versions to become
> unreachable.

Based on https://github.com/w3c/csswg-drafts/issues/666#issuecomment-257889984 ,
should I assume your opinion has changed?
Comment 6 Simon Fraser (smfr) 2016-12-04 23:03:23 PST
After https://trac.webkit.org/changeset/194667 I am cautious about changing iOS <body> overflow:hidden behavior.
Comment 7 Marcelo Freitas 2017-08-14 13:39:23 PDT
Hi guys, do you have any new about this issue? I am facing similar behavior and I would like to know if is there any solution or workaround!
Comment 8 Sameera 2017-08-15 03:44:22 PDT
I'm having same issue. I have find solution with adding class to body with the style position:fixed. But doing that page scroll to the top.

Any other solutions?
Comment 9 David Bokan 2018-03-08 11:09:40 PST
smfr@, do you have a list of pages you saw affected by this we could check again?

I believe iOS WebKit is the only engine that doesn't respect `overflow: hidden` on body so it'd be great for interop if this could be fixed. FWIW, Chrome has had this behavior for several years now and I haven't heard of it causing issues lately. Perhaps sites have been fixed to take it into account by now.
Comment 11 David Bokan 2018-03-09 09:11:10 PST
Thanks smfr@, I've looked into each case. It seems they fall into one of three buckets (mainly using 6S iOS 9):

No overflow: hidden today - site was fixed:
  https://translate.google.dk/translate?hl=da&sl=en&u=http://www.wikihow.com/&prev=search
  Pages on https://surf.miracosta.edu
  (Apple developer documentation) https://developer.apple.com/documentation/ appears fixed

Overflow(-x): hidden still there but site works correctly in both Chrome and Safari (if overflow: hidden were respected).
  https://books.google.com.mx/books?id=vCMIOfrbYrAC&pg=PA83&dq=Funciones+inyectivas,+suprayectivas+y+biyectivas&ei=AiCHSvDONqbKyQTEhO2fDg#v=onepage&q&f=false
    - Appears intentional and correct - scrolling should occur only on the subscroller
    - Safari allows scrolling main frame a little which actually feels wrong since it shifts the UI out of view
    - Respecting overflow: hidden would actually improve the UX here
  https://mobility.agbar.net/mobility-server/
    - There doesn't appear to be any scrolling on the page.
    - Page loads fully zoomed out
    - overflow: hidden commented out but would work regardless, there's no scrolling on the page
  http://www.arnb.org/Festivals.php
    - overflow-x: hidden - there should be no horizontal scrolling
    - Works correctly, all page content is reachable

Problematic on Safari (all work correctly in Chrome):
  http://archives.nyphil.org/index.php/artifact/63041fe8-4b51-4f96-ae82-e40bccf152cd/fullview#page/1/mode/2up
    - No viewport meta
    - Chrome loads the page zoomed out fully so everything is visible
    - Safari iOS 9 locks the page to zoomed in if overflow: hidden is on. When I turn it off using inspector I can zoom out
  desktop version of live.com/hotmail.com/outlook.com
    - Works correctly in Chrome Android
    - There is overflow-x: hidden
    - I'm guessing Safari loads zoomed in because, even in request desktop site, it respects the viewport <meta> which has initial|min|max-scale: 1? Or perhaps related to overflow: hidden as above.
  https://support.eadocsoftware.com
    - No viewport meta
    - Better on Chrome because Chrome sizes layout viewport to match content width, loads zoomed out - the rest is just pinch zoom
    - Why doesn't Safari allow zooming out?
    - iOS 9 loads zoomed in - iOS11 loads zoomed out like Chrome
  1. Open http://output.jsbin.com/sagowo in iOS 9 Safari.
  2. Tap the blue button to make the Bootstrap modal dialog appear.
    - Works correctly in Chrome
    - Chrome shows the page zoomed out
    - No viewport meta tag
    - Why is safari zoomed in so much? Doesn't allow zoom...
    - iOS 11 works, loads zoomed out

In all the problematic cases it looks like the issue is that Safari loads the page zoomed in and then can't scroll because of overflow: hidden. Was this tried before Safari shipped the visual/layout viewport model? Having the split viewport makes these issues quite tractable; Chrome seems to handle these cases rather gracefully so let me explain what we do:

The layout viewport is sized to cover the entire content width. In the case of a desktop page where we fallback to the 980px initial containing block, the layout viewport will be 980px wide. When the page loads, Chrome zoomes out to the minimum possible scale so the visual viewport will match the layout viewport on load. 

overflow: hidden applies only to the layout viewport scrolling. If the user zooms in, they can still pan around but the layout viewport will not scroll from it's original position. This matches the behavior on desktop. If a page is broken in Chrome Android, it's likely also broken on a desktop browser because the layout viewport operates analogously to the browser window.

When you shipped this did you already have a visual/layout viewport? Did overflow: hidden apply only the the layout viewport. Safari on iOS11 loads all the problematic cases zoomed out  just like Chrome so just marking the layout viewport overflow: hidden wouldn't break any of them.
Comment 12 Simon Fraser (smfr) 2018-03-12 13:14:33 PDT
I don't think we had layout/visual viewports when we tried this before.
Comment 13 Radar WebKit Bug Importer 2018-03-21 11:18:10 PDT
<rdar://problem/38715356>
Comment 14 jonjohnjohnson 2018-12-19 13:51:02 PST
bokan@chromium.org thanks for all your help in urging a way forward for compat.

As for a work around, eric@tinymatter.co.uk, marcelopf@ciandt.com, & supun.sameera@live.com, feel free to analyze this setup using sticky positioning, offset margins, and cross axis overflow: https://vault.jonjohnjohnson.com/examples/cssripstop/
Comment 15 Davison 2018-12-19 22:23:07 PST
Honestly this seems like a situation where making iOS Safari work like every other browser would fix a lot more issues than it would break.  As David pointed out, iOS as it is now seems well positioned for finally eliminating this odd behavior.  Whatever tiny fraction of sites that might have a problem are likely very old, already broken on every other browser, and not frequented by almost anyone.

So many people trying to work around this bug have led to a terrible mess of javascript and css hacks that:
1) Frequently don't actually resolve the issue entirely
2) Sometimes appear to expose other iOS Safari issues that complicate things further

Resolving this issue would instantly make modal popups far easier to implement in a simple, cross-platform way.  Thanks to all (especially David) for the work in fleshing this out.
Comment 16 jonjohnjohnson 2018-12-20 13:40:12 PST
Completely agree dlong@nextgentech.net, just trying to offer the only actually clean non js workaround I know, while we wait for compatibility.
Comment 17 Antti Koivisto 2019-05-06 10:15:16 PDT
Created attachment 369132 [details]
patch
Comment 18 Simon Fraser (smfr) 2019-05-06 10:33:02 PDT
Comment on attachment 369132 [details]
patch

View in context: https://bugs.webkit.org/attachment.cgi?id=369132&action=review

> Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingTree.h:61
> +#if PLATFORM(IOS_FAMILY)
> +    void rootScrollingNodeScrollabilityDidChange(bool scrollable);
> +#endif

Shouldn't this be state on a FrameScrollingNode? I would think that iframe have similar logic?
Comment 19 Antti Koivisto 2019-05-06 10:38:21 PDT
> Shouldn't this be state on a FrameScrollingNode? I would think that iframe
> have similar logic?

State is in FrameScrollingNode. This is just to pass things to the main UIScrollView (which is only accessible via PageClient etc).
Comment 20 Antti Koivisto 2019-05-06 10:43:20 PDT
Created attachment 369135 [details]
patch
Comment 21 Simon Fraser (smfr) 2019-05-06 11:20:17 PDT
(In reply to Antti Koivisto from comment #19)
> > Shouldn't this be state on a FrameScrollingNode? I would think that iframe
> > have similar logic?
> 
> State is in FrameScrollingNode. This is just to pass things to the main
> UIScrollView (which is only accessible via PageClient etc).

Oh right, I didn't see it was in the params already. Yay.
Comment 22 Build Bot 2019-05-07 02:42:33 PDT
Comment on attachment 369135 [details]
patch

Attachment 369135 [details] did not pass win-ews (win):
Output: https://webkit-queues.webkit.org/results/12121416

New failing tests:
svg/repaint/remove-border-property-on-root.html
Comment 23 Build Bot 2019-05-07 02:42:36 PDT
Created attachment 369263 [details]
Archive of layout-test-results from ews215 for win-future

The attached test failures were seen while running run-webkit-tests on the win-ews.
Bot: ews215  Port: win-future  Platform: CYGWIN_NT-10.0-17763-3.0.5-338.x86_64-x86_64-64bit
Comment 24 Antti Koivisto 2019-05-07 03:11:24 PDT
Created attachment 369267 [details]
patch
Comment 25 Build Bot 2019-05-07 03:13:13 PDT
Attachment 369267 [details] did not pass style-queue:


ERROR: Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h:70:  Inline functions should not be in classes annotated with WEBCORE_EXPORT. Remove the macro from the class and apply it to each appropriate method, or move the inline function definition out-of-line.  [build/webcore_export] [4]
Total errors found: 1 in 13 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 26 Antti Koivisto 2019-05-07 03:20:30 PDT
Created attachment 369268 [details]
patch
Comment 27 Build Bot 2019-05-07 03:22:18 PDT
Attachment 369268 [details] did not pass style-queue:


ERROR: Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h:70:  Inline functions should not be in classes annotated with WEBCORE_EXPORT. Remove the macro from the class and apply it to each appropriate method, or move the inline function definition out-of-line.  [build/webcore_export] [4]
Total errors found: 1 in 11 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 28 WebKit Commit Bot 2019-05-07 05:02:31 PDT
Comment on attachment 369268 [details]
patch

Clearing flags on attachment: 369268

Committed r245006: <https://trac.webkit.org/changeset/245006>
Comment 29 WebKit Commit Bot 2019-05-07 05:02:33 PDT
All reviewed patches have been landed.  Closing bug.
Comment 30 Davison 2019-05-07 13:16:31 PDT
Am I reading this correctly that with the issue resolved WebKit will now no longer allow the body to scroll if overflow: hidden is set?  If so that is awesome!  How long does it typically take a patch in WebKit to land in an official iOS release?
Comment 31 Simon Fraser (smfr) 2019-05-07 13:28:53 PDT
Correct. We don't make statements about future releases.