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

I just learned about a new and uncommon CSS unit. vh and vw measure the percentage of height and width of the viewport respectively.
I looked at this question from Stack Overflow, but it made the units look even more similar.
How does vw and vh unit works
The answer specifically says
vw and vh are a percentage of the window width and height,
respectively: 100vw is 100% of the width, 80vw is 80%, etc.
This seems like the exact same as the % unit, which is more common.
In Developer Tools, I tried changing the values from vw/vh to % and viceversa and got the same result.
Is there a difference between the two? If not, why were these new units introduced to CSS3?

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>

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>

A percentage of the full viewport width. 10vw will resolve to 10% of the current viewport width, or 48px on a phone that is 480px wide. The difference between % and vw is most similar to the difference between em and rem.
A % length is relative to local context (containing element) width, while a vw length is relative to the full width of the browser window.

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.

the vw (view-width) and vh (view-height) units are relational to the view-port size, where 100vw or vh is 100% of the view-port's width/height.
For example,
if a view-port is 1600px wide, and you specify something as being 2vw, that will be the equivalent of 2% of the view-port width, or 32px.
% unit is always based on the parent element width of the current element

There is a difference that has not necessarily been raised. 100vw includes the width of the scrool bar, while 100% does not include it. It is a small difference, but important when doing design.

The difference between % and vw is most similar to the difference between em and rem. A % length is relative to local context (containing element) width, while a vw length is relative to the full width of the browser window.

Related

CSS unit vw includes width of a physical scrollbar, causing problem for height in vw

For example: I have an element which takes the full width of the viewport. I want its min-height to be half of its width, to get a ratio of 1:2.
On a 1600px wide desktop monitor the element's width would be about 1583px (monitor width minus scrollbar width), but its min-height would be 800px, because vw doesn't substract the scrollbar's width. So that would not be a 1:2 ratio.
An easy solution would be padding-top: 50%;, but if there's text within the element, that doesn't work. Alternative: a left floating pseudo element ::before with padding-top: 50%; would create the desired min-height in the ratio of 1:2, but that would be kinda hacky.
Am I missing something? Is there any clean way?
First thing you should do is include the following so the default padding and margins given by the web browser are removed:
* {
padding: 0;
margin: 0;
}
For the element you want to have 100vw and half height:
.half_height{
width: 100vw;
aspect-ratio: 2/1;
}
.container {
Width: calc(100vw - calc(100vw -100%));
Height: 50vh;
}

CSS - how to change browser height and have website be unaffected?

For example, when you change the height of the browser while you're here on Stack Overflow, the content on the page doesn't change. However, if you visit my portfolio: http://seanrobenalt.com/ and change the browser height, some elements get scrunched up. Can't seem to figure out what's going on.
What's going on is that you've set the content as follows:
.header-logo {
background-color: rgba(229,229,229,0.4);
box-sizing: border-box;
display: block;
height: 10vh;
padding-top: 10px;
position: relative;
text-align: center;
width: 10vh;
}
Your height and width are set to height: 10vh; respectively width: 10vh;.
And what is vh short for? It's short for viewport-height andvh is a measurement unit, but unlike px it's not absolute.
Something that is 10px in height or width, will ALWAYS be 10px in height or width, no matter how you resize the window, because we're talking the static physical pixels on your screen.
vh, vw, or % on the other hand are relative units of measurement. Take % for instance. If you make a div, that is 100% in width – It will stretch the length of the entire parent element. And if the parent element is 100px wide, then the child element will be 100% of 100px which is.... 100px wide. if you set it to 50% of 100px – It's 50px wide.
So what happens if you set an element to 100vw? It can be simplest described as 100% of the entire browser width – or "Viewport".
So something that is 100vh will be 100% of view-height. (viewport height).
And your image is 10vh, which means, it will always be 10% of how high the browser window is. So if the browser is resized to be exactly 500px high – Your image will be 50px high.
What you need to do is set the size of the image in px for it always keep it's height and width.
I suggest you setup a little playground of a few divs, and start playing around with different measurement types.
Make a few divs that are using width: 100px; height: 200px; width: 100%; height: 100%; width: 100vw; height: 100vh; And place the divs in each other and see what happens.
Hope this helps.
You're calculating the layout of various elements on your page by using the vh (viewport height) unit. 100vh is equivalent to the height of your browser window at any given moment, so resizing the browser is doing exactly what it was coded to do.
Example element I see inspecting your site:
.full-hero {
background-color: #c7dbfc;
background-size: cover;
box-sizing: border-box;
height: 90vh;
padding-top: 10vh;
}

How to make an image's width resize itself with a defined height

I am trying to make an image resizable.
I have a specific height for this image: height: 100% (inside a container) and a width: auto; (i want the width to be adapted to the height about the natural image size).
Everything works fine when i access the page, but when i resize the window, the height is correctly resized, but the width keeps its initial value, i want it to be proportional (like when i access the page for the first time) to the height.
Is there a way to do it in CSS ? If not, what is the more optimize solution ?
Here is an illustration in code:
HTML
<div class="container">
<img alt="test" src="/img/test.png">
</div>
CSS
.container {
height: 100px;
width: 100%;
}
.container img {
height: 100%;
width: auto; //i need it to be adapted to each height about the natural image's dimensions
}
UPDATE
Here is a jsfiddle
http://jsfiddle.net/CRGj6/1/
Sometime it works sometime it doesn't...
window resize affects only the width of the element but not the height. It is kinda make sense because if you resize the height, more content is scrollable that means don't do anything to width but to increase the scrollbar length (so more content to be scrolled). Assuming that you want to preserve the aspect ratio of the image,
.wrapper .container img {
position: relative;
height: auto;
width: 100%;
}
would be the solution to this problem.

Limit the height of a responsive image with css

My end goal is to have a fluid <img> that won't expand past an explicitly set height of a parent/grandparent element using only css.
Currently I'm doing this with a normal (max-width:100; height:auto;) fluid image and javascript by reading the height/width attributes from the img tag, calculating the aspect ratio, calculating the correct width of the image at the desired height restriction, and applying that width as a max-width on the image's container element. Pretty simple, but I'd love to be able to do it without javascript.
height:100%; width:auto; doesn't work the same as its transverse, and I've made some attempts with Unc Dave's ol' padded box and absolute positioning that function but require knowing the aspect ratio of the image beforehand and therefore cannot be applied across images that have different proportions. So the final requirement is the css must be proportion agnostic.
I know, I know, the answer to this question is probably sitting next to the unicorn farm, but I thought I'd throw it out there anyways.
The trick is to add both max-height: 100%; and max-width: 100%; to .container img. Example CSS:
.container {
width: 300px;
border: dashed blue 1px;
}
.container img {
max-height: 100%;
max-width: 100%;
}
In this way, you can vary the specified width of .container in whatever way you want (200px or 10% for example), and the image will be no larger than its natural dimensions. (You could specify pixels instead of 100% if you didn't want to rely on the natural size of the image.)
Here's the whole fiddle: http://jsfiddle.net/KatieK/Su28P/1/
I set the below 3 styles to my img tag
max-height: 500px;
height: 70%;
width: auto;
What it does that for desktop screen img doesn't grow beyond 500px but for small mobile screens, it will shrink to 70% of the outer container. Works like a charm.
It also works width property.
You can use inline styling to limit the height:
<img src="" class="img-responsive" alt="" style="max-height: 400px;">

Vertical Pagination of Divs

What I want to do is setup multiple div's that each contain the contents of an entire page. Each div should be centered in the viewport and fill it entirely. Each successive div should be evenly spaced vertically based on the variable height of the viewport. For example say I have a view of 800x600 then each div should be this size and stacked. So, if I scrolled down exactly 600px I would only see page 2 div, 1200px I'd only see page 3 div. I don't have any code or example to share and my exhausted searches have turned up nothing of this sort. Is this possible with just css?
You simply have to give your html, body & divs a height: 100%;:
html, body {
height: 100%;
}
div {
height: 100%;
margin-bottom: 5px;
}
http://jsfiddle.net/KMMjv/
Because this would vary depending on the size of the user's browser window you would need to JavaScript to detect screen height and position them accordingly. Although you could set the height of each div with just CSS (height: 100%;) you would need to set the top with JS.
Here is a working JSBin: http://jsbin.com/ogokef/edit#preview
Use the following units:
vh for viewport height
vw for viewport width
html, body {
height: 100vh;
}
div {
height: 100vh;
width: 100%; /* you can use 100vw too, but for height it must be vh */
}

Resources