DEV Community

loading...
Cover image for 100vh problem with iOS Safari

100vh problem with iOS Safari

maciejtrzcinski profile image Maciej Trzciński 🌱🇵🇱 Originally published at Medium Updated on ・2 min read

100vh

As you see, the web content will be 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

This problem we will receive when we just put height: 100vh for mobile devices. Mobile device calc all browser(top bar + document + bottom bar) as 100vh, and it’s little annoying when we must have 100vh page, unfortunately it doesn’t work like on desktop browser and we have to make a little more effort to receive the same result.

The 100vh problem on mobile devices is really annoying, everyone knows. I have a simple recipe to solve that problem.

To solve this problem, we need a JS and a CSS or just only the CSS (in the second solution):

1. JS & CSS solution

Let’s get started from 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 set new style property with var(--app-height) with the current window height, this property we can use in the CSS file.

: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

var(--app-height) — it’s a reference to --app-height variable that we created previously in a JS file.

2. CSS solution (not recomended)

The second solution is --webkit-fill-available this will ignore safari and iOS native bars, and fill only the document view, but this solution doesn't protect us at Android devices.

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 (9)

pic
Editor guide
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

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
chrisschwartze profile image
Chris Schwartze

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
clivend profile image
clivend

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. 🙏