DEV Community

Cover image for 100vh problem with iOS Safari
Maciej Trzciński 🌱🇵🇱
Maciej Trzciński 🌱🇵🇱

Posted on • Updated on • Originally published at Medium

100vh problem with iOS Safari

100vh

The web content it's outside the viewport although we used 100vh (the red opacity box with 100vh text).

.section {
    height: 100vh; // bad approach 
}
Enter fullscreen mode Exit fullscreen mode

The problem you have been receiving after adding the height: 100vh to mobile resolutions. It happens due to the calculation method which Safari and Chrome are using. Mobile devices calc browser viewport as (top bar + document + bottom bar) = 100vh. I had a hard time with 100vh when the page have to have a section filled the whole screen. After a couple of hours, I've found the solutions that I show you.

They are two solutions, the first needs JavaScript and CSS, the second solution required only CSS.

1. JS & CSS solution

Let’s get started first with the JS file:

const appHeight = () => {
    const doc = document.documentElement
    doc.style.setProperty('--app-height', `${window.innerHeight}px`)
}
window.addEventListener('resize', appHeight)
appHeight()
Enter fullscreen mode Exit fullscreen mode

appHeight function has sets new style property var(--app-height) including current window height, --app-height it is necessary for next steps.

:root {
   --app-height: 100%;
}

html,
body {
    padding: 0;
    margin: 0;
    overflow: hidden;
    width: 100vw;
    height: 100vh;
    height: var(--app-height);
}
Enter fullscreen mode Exit fullscreen mode

In the previous step I've created the reference --app-height, wrapping in the var() I've received CSS variable var(--app-height). This variable is allowed to read values created by JS.

2. CSS solution (not recommend)

The last, but not the least solution is --webkit-fill-available, this solution works only on Apple devices, it won't solve the problem on Android devices. I don't recommend this solution, but it's worth showing.

height: 100%;
height: -webkit-fill-available;
Enter fullscreen mode Exit fullscreen mode

Thank you for your attention! I’ll appreciate your feedback.

If you like this article, follow me on Twitter @MaciejDEV

Discussion (10)

Collapse
fabiogiolito profile image
Fabio Giolito

My approach is to disable the show/hide of the safari bars by preventing the body from scrolling. That way the content area height is constant.

<body>
    <div class="app">...</div>
</body>
Enter fullscreen mode Exit fullscreen mode
body {
    height: 100vh;
    height: -webkit-fill-available;
    overflow: hidden;
}
.app {
    height: 100%;
    overflow: auto;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
maciejtrzcinski profile image
Maciej Trzciński 🌱🇵🇱 Author

Hi, It will work, but you have to remember about for example scrollTo and #anchors in this solution.

Collapse
davidhbeck profile image
david • Edited on

nice! thanks for posting, this is the most effective solve I've found.

something thing I noticed after implementing this solution is that it can trigger the fabled 'jumpy scroll', referenced in the stack overflow post I'm sure we all landed on before finding this post. stackoverflow.com/questions/371122...

as a workaround I created two css variables, one for the fixed "starting" height, and another "dynamic" height that is only used for the shopping cart, mobile menu and other fixed-position elements that require 100% screen height.

pasted below in case someone else runs into the same issue!


// set up css var for starting app height. this will not change on resize so we can avoid the jumpy scroll issue
const appHeight = () => {
const doc = document.documentElement;
doc.style.setProperty('--app-height', ${window.innerHeight/10}rem)
};
window.addEventListener('orientationchange', appHeight);
appHeight();

// set up css var for dynamic app height. this is just for the cart and mobile menu since they need to be fixed to size at all times.

const dynamicAppHeight = () => {
const doc = document.documentElement;
doc.style.setProperty('--dynamic-app-height', ${window.innerHeight/10}rem)
};
window.addEventListener('resize', dynamicAppHeight);
dynamicAppHeight();

Collapse
jochenthomas profile image
jochenthomas

Hi,
see: dev.to/admitkard/mobile-issue-with...
Same issue, but again - on current Safari it is NOT working! Even on Android devices, I see the same issue.

So is there a working solution if the address bar moves away (no resize/switch to landscape etc.).

Collapse
chrisjayden profile image
MultipleHats

I’m confused 🤣

So what are you saying? That the JS solution in this thread doesn’t work but the one you linked does?

Collapse
kieransweeden profile image
Kieran Sweeden

This majorly helped with a college project of mine, thank you for writing this!

Collapse
mrvaa5eiym profile image
mrVAa5eiym

Hi could you please also illustrate the problem? thanks!

Collapse
maciejtrzcinski profile image
Maciej Trzciński 🌱🇵🇱 Author

Hi clivend,

Yes, sure I will illustrate the problem today/tomorrow. Thanks for letting me know what is missing!

Collapse
ipscodingchallenge profile image
ips-coding-challenge

Actually, it's not only on safari. I had the exact same problem on chrome / brave and used the first solution for one of my latest projects ;)

Collapse
maciejtrzcinski profile image
Maciej Trzciński 🌱🇵🇱 Author

Hi ips-coding-challenge,

yes, you are right, I missed issue with OnePlus what I had last year. 🙏