Dynamic viewport units: svh, lvh and dvh

Understand why 100vh overflows on phones, and build full-height sections that fit with small, large and dynamic viewport units.

  • Beginner
  • 7 min read
  • Updated 17 Oct 2026

What you will learn

  • Build full-height sections that work on mobile
  • Choose between svh, lvh and dvh
  • Provide a fallback for browsers without the new units

Before you start

A hero section with height: 100vh looks perfect in a desktop browser and is cut off at the bottom on a phone. The cause is the mobile browser's toolbars. This lesson explains the problem and the three families of viewport units that fix it.

Why 100vh breaks on mobile

Mobile browsers show an address bar and often a toolbar. To give content more room, they hide these bars as you scroll down, and show them again when you scroll up. So the visible height of the page changes while you use it.

If vh changed every time the toolbars moved, every element sized in vh would resize during scrolling, and the page would jump. To avoid that, mobile browsers made vh a fixed value based on the largest possible viewport, with the toolbars hidden.

The result: when the page first loads with the toolbars showing, 100vh is taller than the visible area. The bottom of your "full-screen" hero, often where the call-to-action button sits, is hidden under the toolbar.

Three new viewport sizes

The CSS Values and Units Level 4 specification defines three viewport sizes, each with its own units:

UnitsViewportSize on mobile
svh, svwSmall viewportToolbars fully shown: the smallest visible area
lvh, lvwLarge viewportToolbars fully hidden: the largest visible area
dvh, dvwDynamic viewportWhatever is visible right now; changes as toolbars move

On desktop browsers, where toolbars do not slide away, all three are usually the same as vh and vw.

There are also logical versions, svi, svb, lvi, lvb, dvi and dvb, for the inline and block directions, plus *vmin and *vmax variants such as svmin. The original vh behaves like lvh in most mobile browsers.

Building a full-height hero

For a section that should fill the screen on first load, use the small viewport:

CSS
.hero {
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-content: center;
  padding: 2rem 1rem;
  text-align: center;
}
HTML
<section class="hero">
  <h1>Build sites that work on every screen</h1>
  <p>A free course in responsive web design.</p>
  <a class="button" href="#start">Start learning</a>
</section>

Three details make this robust:

  1. The fallback comes first. A browser that does not understand svh ignores the second declaration and keeps 100vh. A browser that does understand it uses 100svh. This is progressive enhancement with no feature query needed.
  2. min-height, not height. If the content is taller than the screen, for example at 200 percent zoom or on a short landscape phone, the section grows instead of cutting text off.
  3. svh, not dvh. The hero fits in the smallest visible area, so the button is never hidden. When the toolbars slide away there is a little extra space at the bottom, which is harmless.

Avoid height: 100vh or height: 100svh on sections with text. A fixed height cannot grow, so zoomed or enlarged text overflows and may be cut off. That fails WCAG's Resize Text and Reflow criteria. Use min-height.

Choosing between svh, lvh and dvh

UseUnitWhy
Hero sections and splash screenssvhAlways fits on first load; stable while scrolling
Backgrounds that should never show a gap when toolbars hidelvhCovers the largest area; parts may be hidden under toolbars
App shells, full-screen panels, chat layouts that must match the visible area exactlydvhTracks the real visible height as it changes

Why not always use dvh?

dvh sounds like the perfect answer, because it always matches what you can see. The catch is that it changes during scrolling. Anything sized in dvh resizes as the toolbars move, which can make content below it shift and cause extra layout work while the user scrolls.

Use dvh for elements that do not scroll with the page, such as a fixed full-screen overlay or the outer shell of a web app where an inner area scrolls. Use svh for content in the normal scrolling page.

CSS
/* An app shell: header, scrolling content, footer */
.app {
  height: 100vh;
  height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

.app-content {
  overflow-y: auto;
  min-height: 0;
}

The app fills the visible area exactly, and only the middle row scrolls. min-height: 0 stops the grid row from growing to fit all its content, as in lesson 7.

This is one of the few places where height is the right choice, because the shell's job is to match the screen. Its inner area scrolls, so text can still grow without being cut off.

The on-screen keyboard

The software keyboard on phones is a separate matter from toolbars. In most current mobile browsers, opening the keyboard does not change the viewport units by default. It overlays the page instead. Do not rely on dvh to keep a form field above the keyboard, and test forms on real devices.

Some browsers support an interactive-widget key in the viewport meta tag that changes how the keyboard affects the layout. Support varies, so check MDN and Baseline before using it.

Browser support

Small, large and dynamic viewport units are supported in the current versions of all major browsers. Check their Baseline status on web.dev for details. The fallback pattern above, a vh declaration followed by the new unit, means older browsers still get a working, if slightly imperfect, layout.

If you need to apply several rules only when the units are supported, use a feature query:

CSS
@supports (height: 100dvh) {
  .modal {
    max-height: 90dvh;
  }
}

Testing full-height layouts

DevTools device mode does not simulate toolbars sliding away. Test on real phones:

  1. Load the page fresh, scrolled to the top. Check that the whole hero, including its button, is visible.
  2. Scroll down a little so the toolbars hide, then back up. Check nothing jumps unexpectedly.
  3. Rotate to landscape. A short, wide viewport is where full-height sections most often cover content.
  4. Zoom to 200 percent on desktop and check the section grows with its text.

Summary

  • Mobile browsers base vh on the largest viewport, so 100vh is taller than the visible area when toolbars show.
  • svh is the small viewport, lvh the large one, and dvh the dynamic one that changes as toolbars move.
  • Use min-height: 100svh for heroes, with min-height: 100vh before it as a fallback.
  • Use dvh for fixed overlays and app shells, not for content in the scrolling page.
  • Prefer min-height to height so content can grow when zoomed.
  • The on-screen keyboard is not handled by these units by default; test forms on real devices.

You finished the course

You can now build pages that work from a 320 pixel phone to a wide desktop: with the right viewport, mobile-first CSS, media and container queries, responsive images, fluid type, intrinsic layouts, tested breakpoints, accessible navigation and full-height sections that fit. Take the final quiz to check your understanding, then continue with Web Accessibility Essentials to make sure everything you build works for everyone.