CSS Units - What is the difference between vh/vw and %?

Solution 1:

100% can be 100% of the height of anything. For example, if I have a parent div that's 1000px tall, and a child div that is at 100% height, then that child div could theoretically be much taller than the height of the viewport, or much smaller than the height of the viewport, even though that div is set at 100% height.

If I instead make that child div set at 100vh, then it'll only fill up 100% of the height of the viewport, and not necessarily the parent div.

body,
html {
    height: 100%;
}

.parent {
    background: lightblue;
    float: left;
    height: 200px;
    padding: 10px;
    width: 50px;
}

.child {
    background: pink;
    height: 100%;
    width: 100%;
}

.viewport-height {
    background: gray;
    float: right;
    height: 100vh;
    width: 50px;
}
<div class="parent">
    <div class="child">
        100% height
        (parent is 200px)
    </div>
</div>

<div class="viewport-height">
    100vh height
</div>

Solution 2:

I know the question is very old and @Josh Beam addressed the biggest difference, but there's still another one:

Suppose you have a <div>, direct child of <body> that you want filling the whole viewport, so you use width: 100vw; height: 100vh;. It all works just the same as width: 100%; height: 100vh; until you add more content and a vertical scrollbar shows up. Since the vw account for the scrollbar as part of the viewport, width: 100vw; will be slightly bigger than width: 100%;. This little difference ends up adding a horizontal scrollbar (required for the user to see that little extra width) and by consequence, the height would also be a little different on both cases.

That must be taken into consideration when deciding which one to use, even if the parent element size is the same as the document viewport size.

Example:

Using width:100vw;:

.fullviewport {
  width: 100vw;
  height: 100vh;
  background-color: red;
}

.extracontent {
  width: 100vw;
  height: 20vh;
  background-color: blue;
}
<html>
<body>
<div class="fullviewport"></div>
<div class="extracontent"></div>
</body>
</html>

Using width:100%;:

.fullviewport {
  width: 100%;
  height: 100vh;
  background-color: red;
}

.extracontent {
  width: 100%;
  height: 20vh;
  background-color: blue;
}
<html>
<body>
<div class="fullviewport"></div>
<div class="extracontent"></div>
</body>
</html>

Solution 3:

Thank you for your answer and code example, @IanC. It helped me a lot. A clarification: I believe you meant "scrollbar" when you wrote "sidebar."

Here are some related discussions about viewport units counting scrollbars that I also found helpful:

  • Why does vw include the scrollbar as part of the viewport?

  • Using 100vw causes horizontal cropping when vertical scrollbars are present

  • Prevent 100vw from creating horizontal scroll

  • Difference between Width:100% and width:100vw?

The W3C spec for the vw, vh, vmin, vmax units (the "viewport percentage lengths") says "any scrollbars are assumed not to exist".

Apparently Firefox subtracts scrollbar width from 100vw, as @Nolonar's comment at Difference between Width:100% and width:100vw? observes, citing "Can I Use".

Can I Use, perhaps in tension with the spec (?), says all browsers other than Firefox currently "incorrectly" consider 100vw to be the entire page width including the vertical scroll bar.