Viewport units: vw, vh, vmin, vmax

The viewport is the area where the browser renders the site. This is your screen minus the reserved space of the browser chrome. Sometimes you want to size an element based on that viewport, like a sidebar. This can be done using a unit we’re all familiar with: percentages.


.sidebar { width: 25% }

Let’s set the height equal to the viewport.


html, body { height: 100%; }
    
.sidebar {
  height: 100%;
  width: 100%;
}

What’s going wrong here? Why does html and body require a height? Percentages are relative to it’s parent properties. When the parent’s height is defined by it’s children, there’s no known height to set, so the height is ignored entirely. That means you would have to set the height on every parent element in the DOM tree. You could also use the new viewport units.


Viewport-percentage lengths

The viewport units are a new set of units designed for the challenges we face today. One-pagers, full-width grids, typography, and many other things rely on the size of the viewport. Previously, we hacked these challenges using percentages as mentioned earlier, or JavaScript.

This new set of units consists of four different units. Two for each axis, and a minimum and maximum value of the two.

  • vw: 1/100th viewport width
  • vh: 1/100th viewport height
  • vmin: 1/100th of the smallest side
  • vmax: 1/100th of the largest side

Note: IE9 uses vm instead of vmin. It does not support vmax.

Just to clarify: 1vmax equals 1vh in portrait mode, whilst in landscape mode, 1vmax will equal 1vw.


Caution: one major drawback

Imagine you’re building a full-width square grid using these units. I suppose that would look something like this:


.grid {}
    
.grid::before,
.grid::after {
  clear: both;
  content: '';
  display: block;
}
    
.grid__item {
  box-sizing: border-box;
  float: left;
  height: 50vw;
  padding: 2em;
  width: 50vw;
}

See the Pen Viewport units by Tim Severien (@timseverien) on CodePen.

At some point, the items will overflow the viewport. On Windows, a scroll bar will appear, slightly shrinking the viewport. On OS X, a smart scroll bar will appear over the content which shows and hides automatically, thus not affecting the viewport. How is that relevant? Here’s a bit of the specification:

“When the value of ‘overflow’ on the root element is ‘auto’, any scroll bars are assumed not to exist.”
http://www.w3.org/TR/css3-values/#viewport-relative-lengths

That means, when the root element’s overflow is set to auto, which is the default value, scroll bars are assumed not to exist. That means 100vw is the width of the viewport, scroll bar included. In OS X, everything will look fine. On Windows however, the two grid items together are wider than the viewport, scroll bar excluded, thus will be unable to render the two blocks next to each other.

Luckily, this is isn’t a difficult problem to overcome. The easiest way is to simply set the parent’s overflow property to hidden if the parent should grow along with the content. If it should scroll, set it to scroll.

If you’re using the latter but you’re annoyed a scroll bar is displayed even when you cannot scroll, you can use JavaScript to compare the element’s height to the amount of scrolling you can do.


var element = document.documentElement;
  
if(element.scrollHeight > element.clientHeight) {
  // Overflow detected; force scroll bar
  element.style.overflow = 'scrollbar';
} else {
  // No overflow detected; prevent scroll bar
  element.style.overflow = 'hidden';
}

For more robust implementations to detect whether a scroll bar is visible or not, see “Crossbrowser JavaScript Scrollbar Detection” by Tyler Cipriani or “Detect If a Page Has a Vertical Scrollbar” on Stack Overflow if you prefer jQuery.

Real-world usage

A very common use for these units is typography. With the viewport units, you can easily put text over the entire width or height of the screen, like so:

vw example:

See the Pen Viewport units by Tim Severien (@timseverien) on CodePen.

vh example:

See the Pen Viewport units by Tim Severien (@timseverien) on CodePen.


Hopefully the above has given you an insight into the wonderful world of viewport units.

Want to become a better web developer?

Join over 25,000 other developer & designers who get awesome links to the best news and articles each week delivered directly to their inbox.

Tim Severien

Tim Severien is an ambitious front-end developer with passion for code, design, UX, teaching and writing. He publishes articles and experiments all around the web, but they come together on timseverien.com.


This entry was posted in CSS.

17 Comments

  1. Howdy!
    super great article – honestly this is the first time I read about these units. I was reading this with a futurama fry face “reaaalyyyy?”,
    Well anyway. About the whole scrollbar situation: Is there a good way around this? I mean would I have to detect a windows platform and set the parent container to scroll; ? Or am I confused now?
    Thanks a lot for writing this down anyway!
    n

    • Howdy to you too! Setting the parent’s overflow to scroll auto should definitely work. I’ll add a few options to the article how to work around this thing. Thanks for your comment!

    • Hey tim,
      thanks for adding the part of how to circumvent the scrollbar problem!
      Cheers

  2. A nice read!

    Thanks for the part about applying this unit of measurement to text. Amazingly, I had not come across this application before.

    Support ain’t too bad either: http://caniuse.com/#search=Vh

    • Thank you! Yeah, the property is ready for production in my opinion. If the used unit is not supported, you can easily provide that classic CSS fallback we use for calc() too, like so:

      font-size: 5em;
      /* If vw is supported, font-size is overwritten. If not, UA will use 5em */
      font-size: 20vw;

  3. Yesterday I was thinking that there should be a way for sizing the text relative to the window to avoid too much mediaqueries for some elements’ font-size, and today I found this article not knowing those units even exits… amazing. Thank you! (and thanks to responsive design weekly also).

  4. I always wondered why two 50vw divs wouldn’t sit side by side.

    I never knew that the scrollbar would affect it so cheers!

  5. I didn’t know about this. Thanks 🙂

  6. Amazing Example
    https://github.com/Luanramos/Viewport-Units

  7. Damn you scroll bar, thanks a lot of the article it really helped me.

  8. Hello.

    I’m very interested in web design and started building my own web site.
    I tried to use viewport height to get a nice landing screen and footer when someone visits the mobile version of my site. However the nav bar on mobile is not added in the viewport size calculation.
    This causes extremely annoying jumps in the document because the document is constantly getting resized. (You scroll down nav bar dissapears, document jumps, scroll up, nav bar appears, document jumps, …)

    Any solutions to this?

    • Excellent question!

      I’ve come across this problem as well! Unfortunately, the disappearing of the chrome when scrolling on mobile browsers triggers a resize. Therefor, the document does indeed jump when scrolling, as would it when using percentages to set a height.

      As with the scroll bar mentioned in this article, there is no graceful solution to the problem. In 2013, Paul Kinlan wrote a great article “Building an amazing fullscreen mobile experience” in which he describers several tactics to get rid of the address bar. The Fullscreen API he mentions is one option — but isn’t great. Another method he mentions is using window.scrollTo(0, 1). This allows you to remove the address bar on load. But when a user scrolls back up, it simply reappears and we’re back at start.

      At the end of the day, none of the solutions are graceful and you should either accept that there could be some jumping on mobile browsers or use an alternative method, like using JavaScript.

      You could detect the screen ratio and set a vw instead. When the address bar disappears, the width of the screen remains the same, so no jumping! When resizing the browser, you’ll have to redo it though. Look at the code.

    • Thanks for a great comment!

      Maybe i should have mentioned I know some beginner Javascript/Jquery. I’m currently studying to become a webdev/webdesigner.
      I managed to somewhat solve the issue. The main annoying thing on the mobile auto resizing was the jump in the page.
      Let’s say you’re in the middle of your document and your url bar goes away. A viewport resize triggers and every element with ‘vh’ will get longer. Your document becomes longer, but more importantly the stuff that got longer in the first half is what makes your browser jump. The elements that you haven’t seen yet in the second half also get longer but they don’t affect your current position (our jumpy behavior).

      So in my current project I’m using some Jquery to make the header (full screen landing page) to only load once using a simple bool and then headerHeight = $(window).height();
      I tried to minimize the use of vh in my whole document except for the elements at the bottom. A footer and form 100vh combined.

      I now have a way nicer experience on my android phone than in the beginning. Maybe you already know all this but I thought I’d write it down for other people who got stuck on this like me.

      TL;DR.
      The higher you are in your document the more you should avoid ‘vh’ or use jquery to set the height only once.
      When you’re lower in your document it becomes less noticable and more acceptable to use vh.

    • Your link is broken, I’d like to see the code please.

    • Thanks guys for this interesting discussion, it was very helpful using Your method to set the full-screen element’s height to the window height using jQuery, And managed to fix the in-consistency between mobile browsers. The only problem appears on desktop on a resizable window; This value doesn’t change automatically, I think I can use jQuery’s setinterval() to check the window ‘s height each 1 second or something and readjust the wanted element height accordingly. any way thank you.

  9. Love the article, these units are the shizzle!

  10. thank you so much, that scroll bar problem was driving me crazy, everything looked strange on my old computer and fine on the new retina..overflow: hidden for the hmtl frame and all looking nice now! thanks!!!

This post currently has 17 responses. What do you think?

You can use basic HTML when posting code, please turn all < characters into &lt; or > into &gt;
If the code is multi-line, use <pre><code></code></pre>

Leave a Reply

Your email address will not be published. Required fields are marked *