As of March 2022 new CSS viewport units svh, lvh, dvh, svw, lvw, and dvw are incoming as part of the efforts of Apple, Bocoup, Google, Igalia, Microsoft, and Mozilla to improve the web for developers; as part of a project called Interop 2022. Who had ever thought.
Why these new CSS viewport units?
These new CSS units are there to better reflect the viewport's minimum, maximum and current dimensions. For developers this used to require both CSS and JavaScript.
This means that there has never been a clean or built-in solution for issues regarding viewport height excluding the interface of mobile viewports (the URL bar for instance).
Overview of current viewport units (as of March 2022)
Before we jump into the new CSS viewport units, it's important to know the behaviour of the viewport units that are currently supported by most modern web browsers.
Note: all viewport-relative units hold a value that is relative to 1% of the dimension of the viewport it refers to. This means that 50vh
is equal to 50% of the viewport's height.
vh
Unit vh refers to the height of the viewport.
Before 2017, Chrome for Android would update the value of
vh
whenever the currently visible viewport height changed due to the interface of the browser changing.This caused layout shifts when, for instance, the address bar would move out of view due to scrolling down a web page. Safari for iOS was one of the first mobile web browsers to change the value of the
vh
unit to refer to the largest possible viewport height.Chrome for Android changed the implementation of unit
vh
accordingly in version 56.vw
Unit vw refers to the width of the viewport.
There has been frustration and debate about unit vw including the scrollbar that may or may not be present on the right side of your viewport, causing a horizontal scrollbar when applying
100vw
on an HTML element inside of a scrollable web page.Web browser developers have discussed this and decided not to subtract the scroll bar width from the
vw
unit. Whether the scrollbar's width should be subtracted fromvw
or not depends on whether the web page has content that overflows the root vertically.That means that the web browser can only know whether or not to subtract the scrollbar width if the whole web page has already rendered.
This means that a forced recalculation of styles would occur after the web browser finds out that a scrollbar has appeared due to rendered content overflowing the root.
That is the reason why web browser developers decided to keep the calculation of the
vw
unit as is. Consider reading the how-to section CSS 100vw minus scrollbar width.vmin
Unit vmin refers to the smallest dimension of the viewport. Just like is the case with unit vw, unit vmin needs recalculation to subtract the scrollbar from the viewport width.
vmax
Unit vmax refers to the largest dimension of the viewport. Just like is the case with unit vmin, unit vmax needs recalculation to subtract the scrollbar from the viewport width.
Overview of the new incoming CSS viewport units
svh
Unit svh reflects the smallest possible viewport height that is visible to the user. The smallest possible viewport height excludes all interface elements by the user agent.
By default, the vh unit includes the address bar that comes with a mobile browser.
lvh
Unit lvh reflects the largest possible viewport height visible to the user.
dvh
Unit dvh reflects the current viewport height. This unit excludes the user agent's interface, unlike unit vh, and updates as the current viewport height changes.
Unit
dvh
reflects how much vertical viewport height the user agent's interface currently takes up. For instance, this will change as you scroll down a page on mobile, since the mobile URL bar moves out of your screen.svw
Unit svw reflects the smallest possible viewport width that is visible to the user. This unit's value is static, so it will not be changed if the current viewport's width changes.
lvw
Unit lvw reflects the largest possible viewport width that is visible to the user. Like unit svw, this unit's value is static and will not change.
dvw
Unit dvw reflects the current viewport width that is visible to the user. This value is dynamic and will thus change according to the current viewport width.
svmin
Unit svmin picks the smallest value between units svh and svw.
lvmin
Unit lvmin picks the smallest value between units lvh and lvw.
dvmin
Unit dvmin picks the smallest value between units dvh and dvw.
svmax
Unit svmax picks the largest value between units svh and svw.
lvmax
Unit lvmin picks the largest value between units lvh and lvw.
dvmax
Unit dvmax picks the largest value between units dvh and dvw.
vi
Unit vi refers to the viewport's size in the inline direction. For typical English text, the inline direction refers to the width; writing from left to right. However, for typical Chinese text layouts, the inline direction refers to the height; writing from top to bottom.
svi
Unit svi refers to the viewport's smallest possible size in the inline direction.
lvi
Unit lvi refers to the viewport's largest possible size in the inline direction.
dvi
Unit dvi refers to the viewport's current possible size in the inline direction.
vb
Unit vb refers to the viewport's size in the block direction. For typical English text, the block direction refers to the height; with lines wrapping from top to bottom. For typical Chinese text, the block direction refers to the width; wrapping lines from right to left.
svb
Unit svb refers to the viewport's smallest possible dimension in the block direction.
lvb
Unit lvb refers to the viewport's largest possible dimension in the block direction.
dvb
Unit dvb refers to the viewport's current dimension in the block direction.
Finetuning
Not everything is fixed with the addition of the new CSS viewport units, so here are some issues that I noticed working with viewport relative CSS units.
Mobile keyboards affect viewport height units
Whenever a keyboard appears on a mobile viewport, the value of unit vh
changes.
The viewport units' values can be configured to not take the keyboard into account as proposed in W3C's article on the Virtual Keyboard API.
To do so, use this JavaScript code:
if('virtualKeyboard' in navigator) {
navigator.virtualKeyboard.overlaysContent = true;
}
Units like vmin and vmax need a recalculation, because the viewport width units include the scrollbar's width
Viewport width includes the scrollbar's width, which causes units like vmin to return either the viewport height (if that's the smallest dimension) or the viewport width (if that's the smallest dimension), which includes the scrollbar's width.
This means that you have to create your own version of vmin that compares the viewport's height and it's width excluding the scrollbar's width.
After subtracting the scrollbar width from unit vw, you can use the CSS variable called --vw
you've created inside of CSS function min()
and max()
in order to create your own custom CSS variables called --vmin
and --vmax
. This is how:
:root {
--vmin: calc(min(1vh, var(--vw)));
--vmax: calc(max(1vh, var(--vw)));
}
The same recalculation is required for the new viewport units regarding the smallest and largest dimension: svmin, lvmin, dvmin, svmax, lvmax, and dvmax.
Note: in the code below, CSS variable --scrollbarWidth
refers to the scrollbar's width that you calculated in order to subtract the scrollbar's width from unit vw.
:root {
--svw: calc(1svw - var(--scrollbarWidth) / 100);
--lvw: calc(1lvw - var(--scrollbarWidth) / 100);
--dvw: calc(1dvw - var(--scrollbarWidth) / 100);
--svmin: calc(min(1svh, var(--svw)));
--svmax: calc(max(1svh, var(--svw)));
--lvmin: calc(min(1lvh, var(--lvw)));
--lvmax: calc(max(1lvh, var(--lvw)));
--dvmin: calc(min(1dvh, var(--dvw)));
--dvmax: calc(max(1dvh, var(--dvw)));
}