Safari Viewport Units: Why 100vh Overshoots and How to Use svh, lvh, dvh Correctly
In Safari, 100vh can overshoot the visible area because it uses the large viewport. Learn how to use the new svh, lvh, and dvh units to size elements correctly and avoid common pitfalls.
11 Jan 2026, 04:59 UTC

Why 100vh is Too Tall in Safari
When you set min-height: 100vh on a hero section, you expect it to fill the entire screen. In Safari on iOS, the result is often taller than the visible area because the browser calculates 100vh against the *large* viewport – the size when the URL bar is hidden. When the URL bar is visible, the visible area shrinks, and the hero pushes content below the fold.
Safari’s Three Viewport Sizes
Safari defines three logical viewport heights:
- Small viewport (svh) – assumes the URL bar is expanded.
- Large viewport (lvh) – assumes the URL bar is retracted.
- Dynamic viewport (dvh) – tracks the URL bar as it slides during scroll.
These units were introduced in Safari 15.4 and are now part of the CSS Viewport Units specification. They let developers choose the right measurement for the desired visual effect.
Practical Example: Hero Section with Fallback
/* Fallback for older Safari – 100vh uses the large viewport */
.hero {
min-height: 100vh;
}
/* Modern Safari – 100dvh follows the visible area */
@supports (min-height: 100dvh) {
.hero {
min-height: 100dvh;
}
}
Run this CSS in a browser console on an iOS device. Scroll up and down to see the hero’s bottom edge move with the URL bar when the 100dvh rule applies. On older Safari versions (pre‑15.4) the @supports block is ignored, so the hero stays at 100vh.
Choosing the Right Unit
| Unit | Use When |
|---|---|
| svh | Fixed elements that must never sit under the URL bar, e.g., sticky footers or modals. |
| lvh | Full‑bleed media or backgrounds where a slight overflow is acceptable and you want stable sizing during scroll. |
| dvh | Content that should always match the currently visible area, such as a hero that fills the screen exactly while the URL bar is transitioning. |
Limits and Gotchas
- Reflow Cost:
dvhchanges continuously while the URL bar slides. Applying it to many nested elements can trigger layout thrashing and visible jank. - Keyboard Interaction: On iOS Safari the on‑screen keyboard does not shrink the layout viewport, so
dvhdoes not account for it. For keyboard‑aware inputs, use theVisualViewportAPI instead. - Desktop Safari: The full‑screen and tab‑bar states differ from mobile, so
svh/ lvH/dvhmay not behave identically on macOS Safari. - WebViews: Embedded WebViews or third‑party browsers on iOS may not replicate Safari’s exact viewport behavior; test in the target container.
Common Mistakes to Avoid
- Relying on
100dvhwith no100vhfallback – older Safari will collapse the element to its content height. - Applying
100dvhto long scroll containers – the content will jump as the URL bar moves. - Assuming
svhandlvhbehave the same on desktop and mobile – test on both platforms. - Using the old
-webkit-fill-availablehack – it has known bugs in flex and percentage contexts and is now obsolete.
How to Verify Your Implementation
- Open a test page with two stacked sections: one using
min-height: 100vh, the othermin-height: 100dvh. Scroll up and down; the100dvhsection’s bottom should stay aligned with the URL bar. - Focus an input near the bottom of a
100dvhsection on iOS; the layout should not resize when the keyboard appears. - Check the Safari release notes or a current support table (e.g., caniuse.com) to confirm you are targeting Safari 15.4 or newer.
Takeaway
In Safari, 100vh can overshoot because it uses the large viewport. The new svh, lvh, and dvh units give precise control: use svh for elements that must stay above the URL bar, lvh for stable full‑bleed backgrounds, and dvh for content that should always match the visible area. Always provide a fallback for older browsers and be mindful of reflow costs and keyboard behavior.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.