Bug 141832 - Viewport height is taller than the visible part of the document in some mobile browsers
Summary: Viewport height is taller than the visible part of the document in some mobil...
Status: RESOLVED CONFIGURATION CHANGED
Alias: None
Product: WebKit
Classification: Unclassified
Component: CSS (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2015-02-20 02:40 PST by Nicolas Hoizey
Modified: 2023-12-17 04:11 PST (History)
42 users (show)

See Also:


Attachments
Bottom hidden in iOS Safari in portrait mode (44.38 KB, image/png)
2015-02-20 02:40 PST, Nicolas Hoizey
no flags Details
Full content visible in iOS Safari in portrait mode after scroll (46.68 KB, image/png)
2015-02-20 02:41 PST, Nicolas Hoizey
no flags Details
Bottom hidden in iOS Safari in landscape mode (38.53 KB, image/png)
2015-02-20 02:41 PST, Nicolas Hoizey
no flags Details
iOS Safari in landscape mode goes full screen after scroll (37.63 KB, image/png)
2015-02-20 02:42 PST, Nicolas Hoizey
no flags Details
iOS 15 Floating Address Bar Height Test (1.92 MB, video/mp4)
2021-07-29 11:20 PDT, Paris Morgan
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Nicolas Hoizey 2015-02-20 02:40:04 PST
This description is a duplication from a blog post I did [1], maybe easier to read with illustrations in context:

# Description

When trying to use a 100vh CSS value to build a new interface for a game that would use the full viewport, I discovered that this full height value meant the bottom of the game interface was partialy hidden behind the browser buttons bar or below the "fold" of some mobile browsers.

I first discovered this on my iPhone 5 and iPad 2.

See in attachments what the test page [2] looks like on an iPhone 5, portrait and landscape, before and after scroll (and interface minification).

The 100vh value seems to be computed for when the browser interface is hidden, after a scroll.

There is « VIEW » in viewport, so defining it’s dimensions with hidden parts seems strange… The really sad thing is it doesn't help people trying to develop full-viewport interfaces, for games for example, but not only.

As suggested by Yoav Weiss [3], I first opened a bug in Apple Bug Reporter, got the id 19879505.

# Steps to Reproduce

- Open [2] on iOS Safari with an iPhone in portrait mode, or an iPad in portrait or landscape mode
- The bottom part of the "bottom right" box is not visible, the 100vh height container being taller than the visible part

# Expected Results

I would have expected the viewport size (and the 100vh dimension) to be equal to the visible part of the page in the browser. It’s called VIEWport after all.

I understand it means the viewport changes when the browser interface hides, but I find it better, and necessary for "full viewport" interfaces. Fullscreen API is not available either, so there is no simple way to fix this behavior.

# Actual Results

The bottom part of the "bottom right" box is not visible, the 100vh height container being taller than the visible part

# Configuration

iPhone 5 and iPad 2

# Version & Build

iOS 8.1.3 (12B466), and other versions in the iOS simulator

# Additional Notes

There is a JavaScript library that tries to fix some issues with viewport units in iOS, but it has issues too [4] 

----

[1] http://gasteroprod.com/web/viewport-height-is-taller-than-the-visible-part-of-the-document-in-some-mobile-browsers
[2] http://lab.gasteroprod.com/vub/index-ios-issue.html
[3] https://twitter.com/yoavweiss/status/568145414320492544
[4] https://github.com/rodneyrehm/viewport-units-buggyfill/issues/13
Comment 1 Nicolas Hoizey 2015-02-20 02:40:38 PST
Created attachment 246953 [details]
Bottom hidden in iOS Safari in portrait mode
Comment 2 Nicolas Hoizey 2015-02-20 02:41:10 PST
Created attachment 246954 [details]
Full content visible in iOS Safari in portrait mode after scroll
Comment 3 Nicolas Hoizey 2015-02-20 02:41:32 PST
Created attachment 246955 [details]
Bottom hidden in iOS Safari in landscape mode
Comment 4 Nicolas Hoizey 2015-02-20 02:42:02 PST
Created attachment 246956 [details]
iOS Safari in landscape mode goes full screen after scroll
Comment 5 Benjamin Poulain 2015-02-23 09:25:58 PST
This is completely intentional. It took quite a bit of work on our part to achieve this effect. :)

The base problem is this: the visible area changes dynamically as you scroll. If we update the CSS viewport height accordingly, we need to update the layout during the scroll. Not only that looks like shit, but doing that at 60 FPS is practically impossible in most pages (60 FPS is the baseline framerate on iOS).

It is hard to show you the "looks like shit" part, but imagine as you scroll, the contents moves and what you want on screen is continuously shifting.

Dynamically updating the height was not working, we had a few choices: drop viewport units on iOS, match the document size like before iOS 8, use the small view size, use the large view size.

From the data we had, using the larger view size was the best compromise. Most website using viewport units were looking great most of the time.
Comment 6 Nicolas Hoizey 2015-02-23 09:32:26 PST
Thanks for the explanation.

I suppose I will have to use JS instead of CSS for positioning the interface elements and adjust according to the "real" viewable area… :-/
Comment 7 Benjamin Poulain 2015-02-23 09:47:32 PST
(In reply to comment #6)
> Thanks for the explanation.
> 
> I suppose I will have to use JS instead of CSS for positioning the interface
> elements and adjust according to the "real" viewable area… :-/

For positioning, you can look into "fixed" and "sticky" positinioning. Those two modes creates layers that are composited in real time.

Both fixed and sticky positioning follow the view height and WebKit can handle them at 60FPS effortlessly.

If you use JavaScript for positioning while scrolling, you will need to be careful with this:
-resize events are only sent once for the small state or the large state. If you need continuous update, you need to check the window.innerHeight in response to touch events.
-To keep rendering in sync with scrolling, you must respond to each frame in less than ~16ms (in practice, really 9-10ms).
Comment 8 David Bokan 2015-11-30 10:28:07 PST
(In reply to comment #5)
> This is completely intentional. It took quite a bit of work on our part to
> achieve this effect. :)
> 
> The base problem is this: the visible area changes dynamically as you
> scroll. If we update the CSS viewport height accordingly, we need to update
> the layout during the scroll. Not only that looks like shit, but doing that
> at 60 FPS is practically impossible in most pages (60 FPS is the baseline
> framerate on iOS).
> 
> It is hard to show you the "looks like shit" part, but imagine as you
> scroll, the contents moves and what you want on screen is continuously
> shifting.
> 
> Dynamically updating the height was not working, we had a few choices: drop
> viewport units on iOS, match the document size like before iOS 8, use the
> small view size, use the large view size.
> 
> From the data we had, using the larger view size was the best compromise.
> Most website using viewport units were looking great most of the time.

Hi Benjamin, sorry to resurrect this old bug, but I'm working on improving interop between Chromium and Safari here and the choice to use the larger view size seems strange given that the ICB uses the smaller view size.

In particular, this means height:100% and height:100vh will be different which might be surprising. Did you intentionally make the ICB and 100vh unequal? Do you have any examples of pages that look better using this method?

Thanks,
David
Comment 9 Rick Byers 2016-01-25 07:49:31 PST
Note that blink is planning on matching WebKit's behavior here, but it's causing some developer concern.  Details:
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/BK0oHURgmJ4
https://groups.google.com/a/chromium.org/forum/#!topic/input-dev/EBNboiECIAQ

It's still not at all clear this is really the right design for the web long-term.  Perhaps there's a missing API somewhere?
Comment 10 John Meyer 2016-04-27 16:55:10 PDT
It seems to me that the original intent to not reflow while scrolling was a good idea. However, the divergence of height: 100% and height: 100vh breaks the principal of least astonishment at the very least. Rather than choose the largest or smallest icb, I believe users and developers would expect the viewport size to not change at all while scrolling. However, when the scrolling is complete, the viewport should be updated and the elements reflowed.

I realize that reflowing the document after the user has finished scrolling is challenging due to potential changes in scroll position, but maintaining the expected scroll position should be doable. This would allow developers to use 100vh and have it most closely resemble the spec while keeping the desired performance.
Comment 11 hexalys 2016-04-28 16:58:21 PDT
(In reply to comment #9)
> Note that blink is planning on matching WebKit's behavior here, but it's
> causing some developer concern.  Details:
> 
> It's still not at all clear this is really the right design for the web
> long-term.  Perhaps there's a missing API somewhere?

As a dev, the important part is to at least, be able to detect the difference in px via JS. For my own use so far, I have managed to detect the dynamic iOS Safari bar and its size; using a generic debounced resize|scroll event, which updates a CSS class on the document. That give me CSS class updating CSS height accordingly using `calc`. But it remains a fragile hack relying on quite a few assumptions.

The current behavior, *if detectable*, has a significant benefit. This can allow for example, adding a bottom notifications, messages or button bar. But not until a scroll has occurred, and the bottom menu bar is gone; to avoid redundant double bars and/or not to clutter screen space.

As for an API, HTML5 has the BarProp interface for this kind of thing. It seems however that browsers have moved away from exposing any useful values for those attributes, to the point of no longer exposing anything at all on mobile browsers. It seems appropriate to review what BarProp is, what to keep, redefine or add, such as pixel values. Or else BarProp might as well be deprecated...

But if 100vh is context dependent, the browser *should* surely expose that behavior somewhere.
Comment 12 David Bokan 2016-04-29 11:15:46 PDT
(In reply to comment #10)
> It seems to me that the original intent to not reflow while scrolling was a
> good idea. However, the divergence of height: 100% and height: 100vh breaks
> the principal of least astonishment at the very least. Rather than choose
> the largest or smallest icb, I believe users and developers would expect the
> viewport size to not change at all while scrolling. However, when the
> scrolling is complete, the viewport should be updated and the elements
> reflowed.

This is perhaps less astonishing to developers, but to users can be quite frustrating if the developer hasn't thought about it. For e.g., I've seen examples that use vh units to size fonts, which works quite nicely on desktop. On mobile, the page becomes exceedingly annoying as everything resizes and reflows on each change of direction.

> I realize that reflowing the document after the user has finished scrolling
> is challenging due to potential changes in scroll position, but maintaining
> the expected scroll position should be doable. This would allow developers
> to use 100vh and have it most closely resemble the spec while keeping the
> desired performance.

Anchoring the scroll position on relayout is tricky but doable and Chrome's actively working on this. Even if that works perfectly though, I still think that we should make the layout height static *by default*. Exposing this information is a good idea, and we plan to keep window.innerHeight reflecting the status of the top controls (as Safari does IIRC) for motivated developers to make use of it. But I see a static layout as a "pit of success". If a developer doesn't think about this, the default doesn't cause the user a poor experience (even with non-visible differences, constantly changing the layout size causes increased power draw on mobile). If the dev does think about it, they should have the tools to design an even better user experience.
Comment 13 tolga dede 2017-10-30 07:37:43 PDT
cut the shit. this is clearly a FUCKING BUG and NEEDS TO BE FIXED.
Comment 14 Staphan 2018-01-05 07:01:51 PST
I realize that the WebKit developers aren't interested in supporting standards, but what is the correct in getting the correct height in poorly designed browsers such as WebKit? 

Why aren't the developers interested in supplying a way to actually get the height of the content pixels?
Comment 15 Tim 2018-06-08 06:01:30 PDT
Since there still isn't a proper solution to get the actual viewport height on crossbrowser/devices, is there anything planned?

I guess implementing something like 'height: 100vhi;' would solve the majority of problems. This would give back the initial viewport height without the browser chrome (addressbar and other menu's).

So
100vh = device viewport height
100vhi = 100vh - browser chrome

Is that something webkit considers implementing? Would be so helpful and would help speed up everything because we don't need unnecessary javascripts.
Comment 16 RobLi 2018-06-28 11:13:53 PDT
There may be a solution for this if there is an env() variable defined, as suggested here: https://github.com/w3c/csswg-drafts/issues/2630#issuecomment-397536046

If UA's would define their "overlayed" interfaces we could just inset the HTML document.
Comment 17 Adam Stankiewicz 2019-02-04 12:58:18 PST
We cannot easily use calc with 100vh on Safari because of this... Pretending that vertical height of viewport is not changing when it is causes lots of headaches for developers who need to hack their applications just for Safari on iOS because it has issues with calc(100vh - xxx) CSS calculations.

Please re-open this issue
Comment 18 Adam Stankiewicz 2019-02-04 12:58:49 PST
Here's article with more info: https://benfrain.com/the-ios-safari-menu-bar-is-hostile-to-web-apps-discuss/
Comment 19 Simon Fraser (smfr) 2019-02-04 13:00:23 PST
We may revisit this.
Comment 20 Radar WebKit Bug Importer 2019-02-04 13:01:01 PST
<rdar://problem/47796367>
Comment 21 shotafranklin 2019-04-20 07:21:04 PDT
Any updates on this?
Comment 22 Shahar Or 2019-10-06 21:19:54 PDT
A solution should also include the native keyboard, which while in Android Chrome borrows space from the viewport, in iOS Safari it covers over the viewport.
Comment 23 tcurdt 2020-02-06 13:32:01 PST
All of this so the bottom bar can be animated. This is mind boggling.

I understand the goal but right now the difference of 100vh and 100% is a big problem (if one doesn't want to resort to javascript hacks). The very least I would expect is to also adjust the 100% height to the very same 100vh position.

Right now this is completely broken.
Comment 24 Tim 2020-02-06 13:39:15 PST
The CSSWG is actually working on this at the moment.
You can follow it here.

https://github.com/w3c/csswg-drafts/issues/4329
Comment 25 Mike 2020-04-28 15:41:17 PDT
I know I'd be beating a dead horse here, but people only complain about something when it finally bites them in the ass. And that's exactly what I am going to do.

I just want to thank you for making mobile web development significantly more of a pain in the ass than it needed to be. Truly, a magnificent feat.

Maybe one day, we can get around to counting the OS Status Bar and OS Buttons as part of the heigh, sometimes, maybe, just so we can really make sure that mobile web development is truly as hard as it can be.

Or better yet, let's make vh the device's physical height, including the plastic or metal bezel. There's still a bit of use left in vh, so doing that will surely complete your goal of killing it.
Comment 26 Thomas Steiner 2020-04-29 03:15:29 PDT
A tweet [1] that proposed a workaround based on…

```css
body {
  min-height: 100vh;
  min-height: -webkit-fill-available`;
}
```

…went pretty viral (917 Retweets, 4.9K Likes), but even as a workaround this doesn't work universally, since Chrome honors `-webkit-fill-available`, but does something different [2] than Safari, see the demo [3]. 

–——
[1] https://twitter.com/AllThingsSmitty/status/1254151507412496384/
[2] https://twitter.com/tomayac/status/1255436168335953921
[3] https://100vh.glitch.me/
Comment 27 marco.agnoli 2020-10-13 07:01:45 PDT
Please fix this shit, as tolga dede said, this is clearly a BUG.
Comment 28 John Doe 2020-12-24 04:29:45 PST
Hello. I assume this is related to this bug:

https://developer.apple.com/forums/thread/128949

https://stackoverflow.com/questions/62717621/white-space-at-page-bottom-after-device-rotation-in-ios-safari

1. Initial: 100% height match the full visible height
2. As  navigation bar is shown: 100% match the full visible height
3. As navigation bar is removed: 100% match the visible height as if the navigation bar is still there (i.e not 100% of the full visible height)

Happens on rotate and on navigation back_forward, on browser and webview.

On a single page web app with no scroll, updating the viewport height to match 100% to the full visible height when navigation bar is removed should be doable. As using vh units or -webkit-fill-available, tends to render content below the visible viewport or behind the navigation bar.
Comment 29 Juliano 2021-02-26 15:06:27 PST
Just to show my support:  this is a bug.

We have a modal with a fixed top action bar.
On mobile view, it takes the full screen. When the user clicks a form field though, it gets rid of the top bar (which has the actions for SUBMIT and CANCEL) and a few fields. It is really annoying both for devs and users.

We received complaints about the action bar disappearing in Safari and that's why I arrived here. 

I believe you can do better than that.
Comment 30 Juliano 2021-02-26 15:12:06 PST
This is a very good description of the problems this is causing: https://blog.opendigerati.com/the-eccentric-ways-of-ios-safari-with-the-keyboard-b5aa3f34228d
Comment 31 Mike 2021-02-28 11:09:58 PST
I don't know what you guys are complaining about. Why are you still trying to make great rich experiences via webapps and mobile pages, instead of making native mobile apps? How is Apple and Google going to take a cut of your app's revenues and require you to advertise on their app stores, if you don't even have an app on their app stores? Stop being so selfish and think about poor Apple and Google for a second. Nobody wants to be able to simply go to a website and get a great experience. They want to have 1000 apps on their phones. Clearly.
Comment 32 Lincoln Baxter, III 2021-03-24 03:56:07 PDT
Also being affected by this bug. Can't stop safari scroll from moving our mission critical custom controls off-screen.
Comment 33 m.duchemin 2021-07-07 03:27:55 PDT
Also being affected by this bug.

This choice is highly counterproductive, and just makes no sense at the current time.

I will add that even webkit's own debugger doesn't mark CSS properties as "unsuported", making debugging the result of this choice a massive pain unless already knowing that it's a thing that exist.

Using any sort of css property or formula with vh / vw such as:  min-height: calc(100vh - 123px); will just silently fail, without any indication that the property is being ignored.

I appear valid, it doesn't mark the property as invalid, it even "override" previous "valid" properties in the web debugger.

This is obviously a bug, and cannot reasonably be understood otherwise.
Comment 34 Patrick Angle 2021-07-07 09:43:54 PDT
(In reply to m.duchemin from comment #33)
> I will add that even webkit's own debugger doesn't mark CSS properties as
> "unsuported", making debugging the result of this choice a massive pain
> unless already knowing that it's a thing that exist.
> 
> Using any sort of css property or formula with vh / vw such as:  min-height:
> calc(100vh - 123px); will just silently fail, without any indication that
> the property is being ignored.
> 
> I appear valid, it doesn't mark the property as invalid, it even "override"
> previous "valid" properties in the web debugger.
> 
> This is obviously a bug, and cannot reasonably be understood otherwise.

It would be helpful to have a bug tracking your issues with Web Inspector separately. Can you open a new bug in the Web Inspector component and attach a sample page and screenshots of a property that isn't valid but isn't being marked as such? Web Inspector should be marking unsupported property names and values as unsupported in the Styles panel.
Comment 35 Paris Morgan 2021-07-29 11:19:50 PDT
On iOS 15 Beta 4 it seems that the behavior of `100%` and `100vh` changed. Here are my notes on the change:

Device: iPhone 12 Pro Max
iOS 14, iOS 15 Developer Beta 1-3:
- `height: 100%`  address bar minimized          : element flush with address bar, but no lower.
- `height: 100%`  address bar expanded / floating: element flush with address bar, but no lower.
- `height: 100vh` address bar minimized          : element flush with address bar, but no lower.
- `height: 100vh` address bar expanded / floating: element extends to the bottom of the screen.

iOS 15 Developer Beta 4:
- `height: 100%`  address bar minimized          : element flush with address bar, but no lower.
- `height: 100%`  address bar expanded / floating: element extends to the bottom of the screen.
- `height: 100vh` address bar minimized          : element flush with address bar, but no lower.
- `height: 100vh` address bar expanded / floating: element flush with address bar, but no lower.

As you can see, it seems the behavior of `100%` and `100vh` switched when the address bar is expanded / floating.

I have attached a video, and here is a repro: https://8w.8thwall.app/ios-height-tests/. It doesn't repro in CodePen because they have outer html elements which interfere, but here is the code there for reference: https://codepen.io/jparismorgan/pen/oNWqRoK.

So, my question:
- Is this change intentional? Or will it be changed back to the old behavior in the next release? This would be very helpful to know because it will inform whether sites need to handle this change or not.

PS. Happy to file a new bug on this, but it seemed related enough to this existing bug.
Comment 36 Paris Morgan 2021-07-29 11:20:18 PDT
Created attachment 434540 [details]
iOS 15 Floating Address Bar Height Test
Comment 37 Jen Simmons 2021-08-27 16:03:25 PDT
Please test iOS 15 Beta 6.
Comment 38 Jen Simmons 2022-04-26 11:01:55 PDT
After this issue was originally opened, the CSS Working Group official described the VH unit to be the tallest possible length of the viewport. And the CSSWG has defined a new set of units to cover the usecases you describe here — including SVH (shortest), LVH (longest), and DVH (dynamic). We implemented those units, and shipped support in Safari 15.4. 

Thanks for opening this issue. I'm going to close it now, since everything in WebKit matches the current CSS specifications. I hope the new viewport units provide the tools you need.
Comment 39 Nicolas Hoizey 2022-05-12 00:14:20 PDT
Hi Jen, the new units are a great answer to this need, thanks a lot for your efforts with the W3C and webkit teams to get there! 🙏
Comment 40 Andrea Rinaldi 2023-03-16 10:07:22 PDT
I cannot understand why they keep stating that this is a feature. SOLVE THIS SH*T.
Comment 41 kmsh3ng 2023-09-10 07:24:16 PDT
(In reply to Benjamin Poulain from comment #5)
> This is completely intentional. It took quite a bit of work on our part to
> achieve this effect. :)
> 
> The base problem is this: the visible area changes dynamically as you
> scroll. If we update the CSS viewport height accordingly, we need to update
> the layout during the scroll. Not only that looks like shit, but doing that
> at 60 FPS is practically impossible in most pages (60 FPS is the baseline
> framerate on iOS).
> 
> It is hard to show you the "looks like shit" part, but imagine as you
> scroll, the contents moves and what you want on screen is continuously
> shifting.
> 
> Dynamically updating the height was not working, we had a few choices: drop
> viewport units on iOS, match the document size like before iOS 8, use the
> small view size, use the large view size.
> 
> From the data we had, using the larger view size was the best compromise.
> Most website using viewport units were looking great most of the time.

Thank your for making safari the next IE. dumbass
Comment 42 artawower33 2023-10-14 08:27:48 PDT
Nice "feature" -_-. The implementation is really shitty
Comment 43 asesom 2023-12-17 04:11:30 PST
It's Apple's Web. We're Just Playing in It