2026-10-17 · 8 min read
- css
- viewport
- layout
The classic viewport units, vh and vw, refer to the layout viewport. On a phone browser that hides its address bar as you scroll, 100vh has often been the tall viewport, so a page sized to 100vh still scrolls while the bar is visible. The small, large, and dynamic units name the three heights people were trying to get from that one unit.
svh is 1% of the small viewport height, the height when browser interfaces are expanded. lvh is 1% of the large viewport height, when those interfaces are retracted. dvh is 1% of the dynamic viewport height, which changes as the interfaces move. The same small, large, and dynamic prefixes exist for width, inline size, block size, and the min and max pairs.
Decide whether the page may change height
Use svh when the layout must fit while the chrome is showing and must not jump. A toolbar, a bottom navigation, and a dialog are usual cases. Use lvh when you are painting something that is allowed to extend under the chrome, such as a background, and you accept overflow while the chrome is visible. Use dvh when the element should track the visible area, and you have checked that the resize does not fight the scroll that caused it.
100dvh on an element that itself changes document height can loop: the bar hides, the unit grows, the page overflows, the bar returns. If a hero jitters, switch that hero to svh and keep dvh for a component that does not affect the document's scroll height.
- Write the unit next to the component, not only in a token.
- Prefer svh for fixed toolbars and full-height app shells.
- Use dvh where a resize is the designed behavior.
- Keep lvh for paint that may sit under the chrome.
Separate percentage height, insets, and the keyboard
height: 100% resolves against the containing block. If that block's height is auto, the percentage does not become the viewport. A broken full-height layout is sometimes a parent with no definite height, and changing vh to dvh will not fix it. Give the parent a viewport unit, or stop using the percentage.
env(safe-area-inset-bottom) and env(safe-area-inset-top) clear the device's unsafe regions. Add them as padding when content must stay clear of the home indicator. They do not replace svh. Adding both a smaller viewport unit and a large inset, without looking at the computed height, double-counts the chrome.
The keyboard affects the visual viewport. Browsers differ on whether dvh shrinks with it, and interactive-widget changes the layout viewport's behavior. Measure with the keyboard open. Record the computed pixel height beside the unit. A rule that is correct for the address bar can still hide a submit button behind the keyboard.
Record the computed pixels with the source rule
The CSS formatter beautifies and minifies. Minify removes comments and collapses whitespace. It does not compute svh, lvh, or dvh, and it does not know the device. Put the explanation in a review note if you are going to minify the sheet.
From the device, copy the specified declaration and the computed pixel height, with the chrome visible, with it retracted, and with the keyboard open. Diff those three notes. Use the JSON formatter if the notes live in a test report, and the Markdown editor for the short decision: this shell is svh because it must not jump. The source token and the pixel value belong in the same paragraph.