Wednesday, December 2, 2015

Using the new CSS unit "vh" and "vw" which is relative to the viewport size, for CSS3

There is a new CSS unit, which is vh, which is 1/100 of the viewport height.  It actually might be more appropriately named cvh, which means centi-viewport-height, just like we have meter and centimeter — denoted by m and cm.
Note that it is not a variable, but a unit, just like px or em.  And because it is a unit, we cannot say:
height: vh;  /* cannot do this */
height: calc(100px - vh);  /* cannot do this */
We have to always put a number in front of it, just like when we say how wide something is, we can say 1 cm, but we cannot usually just say “cm”.  We would say “1 cm”, versus, if it is a variable, we can say “a – b” or “1a – 1b”.

So the following line:

height: 80vh;  /* this is ok */
is fine.  It means the height is to be 80% of the viewport's height.

Note that this is a “relative unit,” just like em is a relative unit, because it is not absolute.  It is relative to how tall the viewport is.  Note that when the user resizes the browser window to make it shorter, then the vh value will change, and the browser will re-display the elements on the page automatically.
So let’s say we are to design a webpage, with the top part introducing our product or company.  This region is to have the size of the whole window, except for 100px, which we want to show half of a 200px tall region, for people to sign up.  So we want to only show the top half of this sign-up region when the page first loads up, to show that the page is continued down below, or just to intrigue the reader to scroll down and read more.
Note that the height of the top region is:
height: calc(100vh - 100px - 8px * 2)
This is so the element is as tall as the viewport, except for 100px less, and the 8px * 2 is to compensate for the top and bottom margins for this region.
(The body element of the page has 8px of margin at the top as well, but because vertical margins collapse, the result is just 8px of top margin, as showing at the top of the page.)
The second region just have 200px of height, as a sign-up region, perhaps including a sign up message and a sign up button.
This design would have been possible using JavaScript if we don’t have this new unit, but using this new unit, we don’t have to rely on JavaScript, and we don’t have to use JavaScript to observe on the window resize event to do any redrawing.
See or for the full window result.  Note that if you resize the window to make it shorter, the elements will be re-drawn according the the new window height.

If a user resizes the window to make it really short, the top section can shrink down and eventually disappear. To prevent that, we can use:
height: calc(100vh - 100px - 8px * 2);
min-height: 200px;
so that it has a minimum height of 200px, as in

Besides the vh unit, there is also vw for viewport width, and vmin, for the minimum of vh and vw, and vmax, for the maximum of vh and vw.  They are just units, and you can use them wherever you want when a length value is expected.  So you can say height: 100vw; That is to say, you can use vw to describe the height, or use vh to describe the width — you are not limited to only using vh to describe the height.
Since older browsers may not support calc, vh, and vw, this is solved by having a rule in front:
height: 600px;
height: calc(100vh - 100px - 8px * 2);
so that the value can fall back to 600px when the browser doesn’t know how to handle the second line.