100vh in Safari on iOS

Update 2021.07.08: There are new viewport units on the way that will finally solve this issue. 100dvh is the one you’re looking for.

When working with Viewport Units there’s this longstanding and extremely annoying bug in Safari on iOS where it does not play nice with the vh unit. Setting a container to 100vh for example will actually result in an element that’s a wee bit too tall: MobileSafari ignores parts of its UI when calculating 100vh.


Image by Max Schmitt

🤔 New to Viewport Units? Ahmad Shadeed has got you covered.

~

Apple/WebKit’s stance is that it works as intended, although it’s not what I (and many other developers) expect. As a result we have to rely on workarounds.

In the past I’ve used Viewport Units Buggyfill or Louis Hoebregts’ CSS Custom Properties Hack to fix this behavior. I was glad to see that Matt Smith recently found a way to have MobileSafari render an element at 100vh using CSS:

~

As I replied on Twitter: Nice, but I’d rather have MobileSafari fix the vh unit, as using -webkit-fill-available for this will only work to achieving 100vh.

If you want to achieve a perfect 50vh for example, using -webkit-fill-available won’t work as you can’t use -webkit-fill-available in calc(). Above that it won’t work when the targeted element is nested somewhere deep in your DOM tree with one its parents already having a height set.

Come ‘on Safari, stop being the new IE6 …

~

UPDATE 2020.05.16 Apparently this -webkit-fill-available workaround can negatively impact the Chrome browser:

Given this it’s recommended to selectively ship -webkit-fill-available to only Safari using a @supports rule that tests for -webkit-touch-callout support:

body {
  height: 100vh;
}

@supports (-webkit-touch-callout: none) {
  body {
    height: -webkit-fill-available;
  }
}

Alternatively you can still use Louis Hoebregts’ CSS Custom Properties Hack, which uses JavaScript:

.my-element {
  height: 100vh;
  height: calc(var(--vh, 1vh) * 100);
}
const setVh = () => {
  const vh = window.innerHeight * 0.01;
  document.documentElement.style.setProperty('--vh', `${vh}px`);
};

window.addEventListener('load', setVh);
window.addEventListener('resize', setVh);

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Join the Conversation

2 Comments

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.