DEV Community

Cover image for Mobile issue with 100vh | height: 100% !== 100vh [3 solutions]
Piyush Kumar Baliyan for AdmitKard

Posted on • Updated on

Mobile issue with 100vh | height: 100% !== 100vh [3 solutions]

So there are various ways to size any element on a webpage.
We are familiar with common CSS units px, em, pt (and uncommon one cm, mm, in) with support from the first version of CSS (https://www.w3.org/TR/REC-CSS1/#units).

With newer viewport units, first support came in 2013 with FF and Chrome being the first ones quickly followed by Safari and Opera. (yes, IE used to suck even in those days).

Now with newer viewport units and a ton on mobile devices, the browser communities don’t seem to agree on how to implement them in mobile devices.

In mobile, vh seems to consider the address bar as part of the viewport (IDK why is it named as ‘view’port then).

On mobile 100vh !== 100%

This creates weird issues with mobile viewport heights like this:

Mobile on 100vh is cut

Now this is an issue and indeed a very frustrating one, but we’ll discuss a couple of solutions one by one.

1. Use 100% instead of 100vh - “DOM tree nightmare”

Now the quickest, and most CSS way is to use 100% in your page for the whole DOM tree till your target element:

100% height through dom tree

This will work correctly on both mobile and desktop websites. However it is very difficult to propagate 100% through every DOM node in the branch of your element, especially if it is buried deep in the tree (however, you might not come across too many use cases like this).

2. Use JS window.innerHeight for your element - “JS hack”

The second way is to use window.innerHeight for your target element, as on mobile, it will always give you the viewable height of the viewport, but again, this again creates a problem as you will have to write this tiny JS for each of your use cases.

So can there be an easy solution, which can give you the best of both worlds?

3. Use custom vh (CSS variable) - best of both worlds

So the solution, (you might find very few solutions floating around for this typeof fix).
Before proceeding with this solution, let's see what are the cons to this. This solution involves using CSS variables (custom properties) and here https://caniuse.com/#search=css%20var, you can see that support for CSS variables came in early 2017 for major browsers, so you might need to think if you want to use this.

Step 1

So here we’ll be creating something like this:
--vh in root html

Now what we have to do is set CSS variable --vh using window.innerHeight.

window.addEventListener('resize', () => { 
  document.querySelector(':root').style
    .setProperty('--vh', window.innerHeight/100 + 'px');
})
Enter fullscreen mode Exit fullscreen mode

Now you will have --vh available in your whole app.

Here comes the second step of this

Step 2

You can now use this variable anywhere in your code

height: calc(100 * var(--vh));
Enter fullscreen mode Exit fullscreen mode

This works like vh (with a little too verbose representation).

  • 100vh - height: calc(100 * var(--vh));
  • 10vh - height: calc(10 * var(--vh));
  • 1vh - height: calc(1 * var(--vh));

And you can use it anywhere in your CSS code.


Read Next

Top comments (8)

Collapse
 
jochenthomas profile image
jochenthomas

Is there any solution on the market?
Esp. on IOS14/Safari we have still the same issue (as already mentioned by Leonardo).

I also tried this:
width: -moz-available; /* WebKit-based browsers will ignore this. /
width: -webkit-fill-available; /
Mozilla-based browsers will ignore this. */
width: fill-available;
But I cannot get it working.

Any advice to have a real height when the address bar gets away (I urgently need to have a "holy grail" design = fixed header + fixed footer and flexible content-area in the middle)?
Thanks for any direction...

Collapse
 
sdoigmm profile image
Steve Doig

This works for me in Chrome on desktop (i.e. it adds the --vh variable to the style of html), but it doesn't add the --vh variable to the style of html in Chrome on a Google Pixel 5. Is this because the --vh variable is only added when the viewport is resized?

(window.addEventListener('resize'...)

Collapse
 
piyushkmr profile image
Piyush Kumar Baliyan

I also added a initial window loaded event, in addition to resize.

Collapse
 
sdoigmm profile image
Steve Doig

I had to add a separate event listener for window's load event to performing the same function to get it to work on mobile.

Collapse
 
torstendittmann profile image
Torsten Dittmann • Edited

It is even worse, when you try to adjust to an activated mobile keyboard with 100vh :D

Collapse
 
piyushkmr profile image
Piyush Kumar Baliyan

Yeah, seems like mobile browsers are unable to do an implementation of the viewport with simplicity. And 100% height is another nightmare in itself. 🤯

Collapse
 
cavalcanteleo profile image
Leonardo

None of those worked on iOS 14

Collapse
 
piyushkmr profile image
Piyush Kumar Baliyan

Will have to check on that.