Also available in: Español · Português · Français · العربية
svh vs dvh vs lvh: CSS viewport units, measured in your browser
What 100vh, 100svh, 100lvh and 100dvh actually resolve to on the device you are reading this on — and which one you probably wanted.
What the CSS viewport units are
A viewport unit is a percentage of the viewport expressed as a length, so 100vh means the full height and 50vw means half the width. What almost nobody realises is how many of them there are: twenty-four. Six axes — width, height, the two logical axes for the writing direction, and the smaller and larger of the two — multiplied by four different ideas of what the viewport even is.
Those four are the interesting part. The small viewport is the space you have with every retractable piece of browser interface showing. The large viewport is the space you have with all of it retracted. The dynamic viewport is whatever is true at this instant. And the fourth is the unprefixed family you already use, vh and vw, which is not a fifth measurement at all — it is defined to be the same as the large one.
That is why the units arrive in a set: svh, lvh and dvh alongside plain vh, and the same four across every axis. They landed in browsers together, which is also why a browser old enough to miss one of them misses all three.
How to use it
- Read the four heights. They are measured in your browser as this page loads, by laying out an element in each unit and reading back what it came to. Nothing is looked up in a table, so the numbers describe the device you are holding.
- Look at the gap. The row underneath is large minus small: the browser chrome that hides once you start scrolling. On a desktop window it is usually zero, which is exactly why this problem stays invisible until somebody opens the page on a phone.
- Scroll, on a phone. The dynamic row changes as the toolbar retracts and returns, and the findings say which end it is currently sitting at. That movement is the specification working as designed, and it is also the reason the dynamic units are not a free upgrade.
100vh is the tall viewport, on purpose
The universal framing is that 100vh is broken on mobile — that browsers get it wrong, that the address bar ruins it, that you need a JavaScript workaround. The framing is inverted. The CSS specification defines the large viewport-percentage units and the default viewport-percentage units against the large viewport size: the viewport sized as though any interface that expands and retracts were retracted. In other words 100vh is 100lvh, deliberately, and it always has been.
The specification then states the consequence in the very next paragraph, without hedging: when those retractable elements are shown, they can obscure content that is sized or positioned using these units. That is not a bug report, it is the design being explained. The unprefixed units let you fill the screen completely, and the price is that a toolbar can sit on top of what you filled it with.
Which makes svh the unit almost everyone reaching for vh actually wanted. The specification describes it as filling the screen without any of its content being obscured when all the dynamic interface elements are shown — and then, in the same breath, calls the small units safer in general but warns they might not produce the most attractive layout once the chrome hides again. Safer and slightly emptier is the trade, and it is stated in the standard rather than discovered in a bug tracker.
The measurement above is the honest version of this claim. Rather than asserting that your browser follows the definition, the page asks it: if vh and lvh come back equal, that is the specification working, and if they ever do not, the tool says so and marks it as the one result here that would be a browser fault rather than a fact about your device.
The dynamic units are not a free upgrade
If svh is a little too short and vh is a little too tall, dvh looks like the obvious answer, and sometimes it is. The specification is unusually direct about what it costs: the sizes of the dynamic viewport-percentage units are not stable even while the viewport itself is unchanged, and using them can cause content to resize while the user scrolls the page — which, it goes on, can be disturbing to the user and costly in terms of performance.
There is also a detail that explains why two phones can behave differently on the same page. Whether a piece of interface retracting changes every viewport unit at once, or instead only shows up as the difference between the small and large sizes, is largely up to the browser. The standard constrains it at both ends — anything that happens as a result of scrolling must fall in the second category, and anything with a steady enough state that re-laying out would help the reader must fall in the first — but between those two rules there is room for browsers to disagree, and they do.
The dynamic units come with one more permission that is worth knowing before you rely on smooth behaviour: a browser is not required to animate them while an interface is expanding or retracting, and may calculate them as though it were fully open or fully closed for the duration. The recommendation is to assume fully retracted. So if you see the dynamic row on this page jump rather than glide, that is a conforming choice rather than a glitch.
What this cannot tell you
The most important limitation is one the specification supplies rather than one we discovered. Some browser interfaces intentionally overlay content and cause no layout shift at all — and therefore have no effect on any of the viewport-percentage lengths. So svh is safer than vh, and it is not a guarantee: an overlay of that kind sits on top of a perfectly-sized svh element and none of these numbers will ever mention it.
The measurement describes this browser, this window and this moment. Rotate the device, open a keyboard, enter full screen, or install a different browser and the numbers change — which is the point, but it means you cannot read a phone's behaviour off a laptop. If the gap row says nothing retracts, that is a true statement about the window you are in and tells you nothing about anyone else's.
There is one thing the page deliberately does not do: recommend a unit. Which one is right depends on whether an element must never be covered, must never leave a gap, or must always fit exactly, and those are three different requirements that no tool can pick between for you. What it can do is show you the size of the difference on real hardware, so the choice is made against a number rather than a guess.
Finally, this measures units, not layouts. A section that overflows may be doing so because of the unit, or because of a margin, a fixed header, or a scrollbar the unit knows nothing about. If the numbers here look right and your page still overflows, the unit is not the culprit.
Why is it free?
The measurement runs in your browser: the page lays out a hidden element in each unit and reads the result. There is no server in the loop, so there is nothing to bill for and no account to create.
Nothing is uploaded and nothing is stored. The numbers exist only in your tab, and reloading the page measures them again from scratch.