Search code examples
cssmobile-safari

SVH units not working properly in mobile Safari


Mobile Safari does not distinguish between the CSS units svh and dvh. These units should yield different heights with the viewport expanded (toolbars retracted), however instead they are yielding the same height.

Safari support for these units was announced in the WebKit blog around a year ago. These units are described in the specification CSS Values and Units Module Level 4.

Test page

This snippet illustrates the bug, as does this webpage. Note that the bug is only visible when using mobile Safari (on an iPhone or iPad, or using the Simulator which comes with Xcode).

body {
  display: flex;
  gap: 1em;
  margin: 0 2em;
}
div {
  border: 5px solid red;
  box-sizing: border-box;
  width: 5em;
  padding-top: 1em;
  text-align: center;
}
div:nth-child(1) {
  background: cyan;
  height: 100vh;
}
div:nth-child(2) {
  background: yellow;
  height: 100svh;
}
div:nth-child(3) {
  background: lime;
  height: 100dvh;
}
div:nth-child(4) {
  background: pink;
  height: 100lvh;
}
<div>100vh</div>
<div>100svh</div>
<div>100dvh</div>
<div>100lvh</div>

Expected behaviour

As the toolbars are collapsed and expanded, the only element which should change size is the one sized with dvh units (the lime-coloured element). The other three elements should maintain a fixed size.

When viewing the page in the small viewport (toolbars expanded), the elements sized with svh and dvh should both exactly fit the viewport, and the element sized with lvh should be larger than the viewport.

When viewing the page in the large viewport (toolbars collapsed), the elements sized with dvh and lvh should both exactly fit the viewport, and the element sized with svh should be smaller than the viewport.

To put it another way, the yellow element should be short, the pink element should be long, and the lime element should switch between short and long.

enter image description here

Actual behaviour

As the toolbars are collapsed and expanded (using the Hide Toolbar menu option), both the elements sized with svh and dvh change their size. Interestingly, the yellow element changes size immediately and the lime element adjusts a split second later. However, the point here is that the yellow element should not change its size.

Here is a screenshot video illustrating this incorrect behaviour of mobile Safari. Captured on an iPhone running iOS 16.4.1.


Solution

  • This bug has been fixed in iOS 17.4 and iPadOS 17.4. 🍾🥂

    ==========

    ORIGINAL ANSWER

    I believe this is a bug in the browser’s rendering engine and I have reported it to Apple.

    UPDATE 1

    I initially reported this using Apple’s Feeback Assistant; reports lodged this way are not available publicly. However, I have just discovered that WebKit has a public Bugzilla system, so I have created this ticket for the issue.

    UPDATE 2

    Feedback from the ticket in Bugzilla indicates that Safari might be behaving as intended. The feedback indicates there may be a distinction between the toolbar being hidden automatically due to scrolling and the toolbar being hidden manually using the Hide Toolbar menu option.

    This might be the expected behavior.

    When the toolbar is automatically hidden due to scrolling, only the dvh sized bar changes. The svh sized bar stays unaffected. This is as expected.

    When you press the “Hide toolbar” option however, you effectively turn off the automatic show/hide functionality. As there no longer is a toolbar that will automatically cover parts of the viewport the small viewport can be interpreted to be the same as the large viewport, similar to desktop browsers.

    I’m not sure what the correct interpretation should be here. It would be interesting to hear from the implementers.

    Do you have a specific use case where it’s important that the small viewport stays unaffected when the user disables the toolbar altogether?

    If manually hiding the toolbar was a permanent change, a state which persists until I make another manual change, I could understand drawing a distinction between this and the scrollbar being hidden temporarily as occurs during scrolling. But it cannot be a permanent change. Manually hiding the toolbar helps reclaim some screen space temporarily when required, but you can’t browse the web with the toolbar hidden. As soon as you need to use the back button or search or type another web address, you need the large toolbar back, which you get by tapping the mini toolbar.

    It’s much more useful for developers if SVH and DVH behave differently from each other — then we can choose the value we want to use. It’s no use whatever for them to behave the same as each other. So I continue in my opposition to the way that SVH units have been implemented in mobile Safari.

    UPDATE 3

    Good news, there has been some movement on this bug in the last few days (November 2023). Firstly, this comment from the person assigned to the bug:

    I agree that this is unexpected behavior.

    The assignee has also posted a fix which he claims resolves the issue, but we will have to wait for that fix to be reviewed and deployed before we can verify that.

    UPDATE 4

    This bug has been fixed in iOS 17.4 and iPadOS 17.4. 🍾🥂