Vertical limit

When I was first styling Resilient Web Design, I made heavy use of vh units. The vertical spacing between elements—headings, paragraphs, images—was all proportional to the overall viewport height. It looked great!

Then I tested it on real devices.

Here’s the problem: when a page loads up in a mobile browser—like, say, Chrome on an Android device—the URL bar is at the top of the screen. The height of that piece of the browser interface isn’t taken into account for the viewport height. That makes sense: the viewport height is the amount of screen real estate available for the content. The content doesn’t extend into the URL bar, therefore the height of the URL bar shouldn’t be part of the viewport height.

But then if you start scrolling down, the URL bar scrolls away off the top of the screen. So now it’s behaving as though it is part of the content rather than part of the browser interface. At this point, the value of the viewport height changes: now it’s the previous value plus the height of the URL bar that was previously there but which has now disappeared.

I totally understand why the URL bar is squirrelled away once the user starts scrolling—it frees up some valuable vertical space. But because that necessarily means recalculating the viewport height, it effectively makes the vh unit in CSS very, very limited in scope.

In my initial implementation of Resilient Web Design, the one where I was styling almost everything with vh, the site was unusable. Every time you started scrolling, things would jump around. I had to go back to the drawing board and remove almost all instances of vh from the styles.

I’ve left it in for one use case and I think it’s the most common use of vh: making an element take up exactly the height of the viewport. The front page of the web book uses min-height: 100vh for the title.


But as soon as you scroll down from there, that element changes height. The content below it suddenly moves.

Let’s say the overall height of the browser window is 600 pixels, of which 50 pixels are taken up by the URL bar. When the page loads, 100vh is 550 pixels. But as soon as you scroll down and the URL bar floats away, the value of 100vh becomes 600 pixels.

(This also causes problems if you’re using vertical media queries. If you choose the wrong vertical breakpoint, then the media query won’t kick in when the page loads but will kick in once the user starts scrolling …or vice-versa.)

There’s a mixed message here. On the one hand, the browser is declaring that the URL bar is part of its interface; that the space is off-limits for content. But then, once scrolling starts, that is invalidated. Now the URL bar is behaving as though it is part of the content scrolling off the top of the viewport.

The result of this messiness is that the vh unit is practically useless for real-world situations with real-world devices. It works great for desktop browsers if you’re grabbing the browser window and resizing, but that’s not exactly a common scenario for anyone other than web developers.

I’m sure there’s a way of solving it with JavaScript but that feels like using an atomic bomb to crack a walnut—the whole point of having this in CSS is that we don’t need to use JavaScript for something related to styling.

It’s such a shame. A piece of CSS that’s great in theory, and is really well supported, just falls apart where it matters most.

Update: There’s a two-year old bug report on this for Chrome, and it looks like it might actually get fixed in February.

Have you published a response to this? :


Ivan Čurić

Not sure why Chrome is singled out, since Safari has the same issue and worse ones.

Ivan Čurić

Sometimes it behaves like it’s over the page and you can’t get rid of it to interact with the page below.

Ethan Marcotte

i do use em for my calculations; i’ve read @adactio’s post, and i’m good with the vh treatment i have, thank you

Nicolas Hoizey

sorry, I didn’t mean to criticize, just suggest an enhancement to font-size: calc(14px + (16 - 14) * ((100vw - 300px)/ (1400 - 300)));


# Shared by Trent Walton on Tuesday, February 7th, 2017 at 8:04pm

# Shared by Simon Owen on Tuesday, February 7th, 2017 at 8:08pm

# Shared by ryo watanabe | 渡辺竜 on Tuesday, February 7th, 2017 at 8:17pm


# Liked by Charles ☕ Stanhope on Tuesday, January 3rd, 2017 at 5:39pm

# Liked by Marc Drummond on Tuesday, January 3rd, 2017 at 7:11pm

# Liked by Pralie Dutzel on Tuesday, February 7th, 2017 at 8:21pm

# Liked by Trent Walton on Tuesday, February 7th, 2017 at 8:21pm

# Liked by Christian Hamann on Tuesday, February 7th, 2017 at 10:23pm

# Liked by Tom Finley on Saturday, January 11th, 2020 at 9:51pm

# Liked by Benjamin Walsh on Saturday, January 11th, 2020 at 10:25pm

# Liked by Adam Argyle on Saturday, January 11th, 2020 at 10:25pm

# Liked by David Hund ✌ on Saturday, January 11th, 2020 at 11:08pm

Previously on this day

4 years ago I wrote Year’s end

Marking the start of 2016.

9 years ago I wrote DOM Scripting, second edition

My first book has been updated (though not by me).

14 years ago I wrote Faster, more intense

George Lucas is infamous for providing limited direction to his actors. His advice generally consists of: