'How to access the real 100vh on iOS in CSS

This is a self Q&A

If you've ever tried to use 100vh in CSS on iOS you will have found that it isn't actually 100vh when the browser chrome is expanded. It's a well documented bug that Apple decided was actually a feature! This is a good read to explain the bug.

So what is the best way to get around this "feature"? Ideally the answer requires no JavaScript (but that seems unlikely), should be clean, not require a bunch of inline styles, and ideally can be opted into in CSS (sometimes you might want the default 100vh).



Solution 1:[1]

Set a root CSS var like so in your stylesheet:

// CSS vars
:root {
    --real100vh: 100vh;
}

Then in JavaScript, on load (or jQuery ready event) and on also on resize, you want to run this code:

    set100vhVar() {
        // If less than most tablets, set CSS var to window height.
        let value = "100vh"

        // If window size is iPad or smaller, then use JS to set screen height.
        if (window.innerWidth && window.innerWidth <= 1024) {
            value = `${window.innerHeight}px`
        }
        document.documentElement.style.setProperty("--real100vh", value)
    }

Now you can simply use the CSS: height: var(--real100vh); wherever you want 100vh to actually be the real 100vh on mobile, and this will simply work!

It looks better if you also add a transition: height 0.4s ease-in-out; on the same element, so it doesn't snap when you scroll down on mobile.

The advantage of using a CSS var to do this is that you can override this whenever you like, for example you might want certain breakpoints to be height: 500px, and this is hard to do if you use an inline style. You can also use this inside calc(), like height: calc(var(real100vh) - 100px); which is useful for fixed headers.

If you use Vue/Nuxt, take a look at how we have implemented that here.

Solution 2:[2]

CSS Grid is the solution.

.grid-container {
  height: 100vh;
  grid-template-columns: 1fr;
  grid-template-rows: 30px 1fr 30px
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 inux