Viewport Units

Difficulty: Intermediate

Viewport units are CSS length units relative to the size of the browser viewport. They enable truly fluid designs that scale proportionally with the browser window, without breakpoints. The four classic viewport units are vw (1% of viewport width), vh (1% of viewport height), vmin (1% of the smaller dimension), and vmax (1% of the larger dimension).

100vw equals the full width of the viewport, and 100vh equals its full height. This makes them ideal for full-screen hero sections (height: 100vh), full-width banners, and proportional sizing. vmin and vmax are particularly useful for maintaining proportions regardless of orientation: on a 1000x600 screen, 1vmin is 6px (1% of 600) and 1vmax is 10px (1% of 1000). vmin is excellent for responsive font sizes that scale well in both portrait and landscape orientations.

The classic vh unit has a significant problem on mobile browsers. Mobile browsers have dynamic toolbars (address bar, bottom navigation bar) that appear and disappear as the user scrolls. The traditional vh unit represents the viewport height when these toolbars are visible (the smallest state), which means 100vh is often taller than the visible area when toolbars are shown, or shorter than the visible area when toolbars are hidden. This causes content to be cut off or leave gaps.

CSS introduced three new viewport height units to solve this: svh (small viewport height - viewport when all toolbars are shown, the smallest possible), lvh (large viewport height - viewport when all toolbars are hidden, the largest possible), and dvh (dynamic viewport height - the current actual viewport height, which changes as toolbars appear and disappear). Each has a corresponding width unit (svw, lvw, dvw) and min/max variants (svmin, lvmin, dvmin, etc.).

For most use cases, dvh is the best choice for full-height layouts on mobile because it reflects the actual visible area. Use svh when you need content to always fit without scrolling (even with toolbars visible). Use lvh for background images or decorative elements where a brief gap during toolbar transitions is acceptable. On desktop browsers where toolbars do not change size, all three values are identical to vh.

Code examples

Basic Viewport Units

/* Full-screen hero section */
.hero {
  width: 100vw;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #1e293b;
  color: white;
}

/* Half-viewport sections */
.split-left {
  width: 50vw;
  height: 100vh;
  float: left;
}
.split-right {
  width: 50vw;
  height: 100vh;
  float: left;
}

/* Responsive font sizing with vmin */
.responsive-title {
  font-size: 5vmin; /* Scales with the smaller viewport dimension */
}

/* Square element that adapts to viewport */
.viewport-square {
  width: 30vmin;
  height: 30vmin; /* Always a perfect square */
}

vw and vh create viewport-proportional sizes. vmin is excellent for responsive typography and maintaining square proportions because it uses the smaller dimension, preventing overflow in either orientation.

The Mobile Viewport Problem

/* PROBLEM: 100vh on mobile can cause overflow */
.hero-broken {
  height: 100vh; /* May be taller than visible area on mobile */
  /* Browser toolbar hides part of the content */
}

/* SOLUTION 1: Use dvh (dynamic viewport height) */
.hero-dvh {
  height: 100dvh; /* Adjusts as toolbars appear/disappear */
}

/* SOLUTION 2: Use svh (small viewport height) */
.hero-svh {
  height: 100svh; /* Always fits even with toolbars shown */
}

/* SOLUTION 3: Fallback for older browsers */
.hero-fallback {
  height: 100vh;              /* Fallback */
  height: 100dvh;             /* Modern override */
}

/* SOLUTION 4: JavaScript fallback */
/* Set --vh custom property via JS:
   document.documentElement.style
     .setProperty('--vh', window.innerHeight * 0.01 + 'px');
*/
.hero-js {
  height: calc(var(--vh, 1vh) * 100);
}

The classic 100vh is unreliable on mobile. dvh dynamically tracks the visible height. svh gives the smallest guaranteed height. The fallback pattern uses vh for old browsers and dvh as a progressive enhancement.

Fluid Typography with clamp and Viewport Units

/* Fluid font sizes that scale between min and max */
h1 {
  /* Minimum 1.5rem, scales with 4vw, maximum 3.5rem */
  font-size: clamp(1.5rem, 4vw, 3.5rem);
}

h2 {
  font-size: clamp(1.25rem, 3vw, 2.5rem);
}

p {
  font-size: clamp(1rem, 1.5vw, 1.25rem);
  line-height: 1.7;
}

/* Fluid spacing */
.section {
  padding: clamp(24px, 5vw, 80px);
}

/* Fluid container width */
.container {
  width: clamp(320px, 90vw, 1200px);
  margin: 0 auto;
}

/* Without clamp (older approach) */
.legacy-title {
  font-size: calc(16px + 2vw);
  /* Problem: no minimum or maximum cap */
}

clamp(min, preferred, max) combined with viewport units creates fluid typography that scales smoothly without breakpoints. The text never gets smaller than min or larger than max, with smooth scaling in between.

svh, lvh, and dvh Comparison

/* Small viewport height: toolbars visible (smallest) */
.section-svh {
  min-height: 100svh;
  /* Content always fits without scrolling */
  /* Good for: landing page hero sections */
}

/* Large viewport height: toolbars hidden (largest) */
.section-lvh {
  min-height: 100lvh;
  /* Fills the full space when toolbars collapse */
  /* Good for: background images, decorative sections */
}

/* Dynamic viewport height: tracks actual visible area */
.section-dvh {
  min-height: 100dvh;
  /* Updates in real time as toolbars change */
  /* Good for: most full-height layouts */
}

/* Combining with other units */
.sticky-footer {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
.sticky-footer main {
  flex: 1;
}
.sticky-footer footer {
  /* Footer sticks to the actual bottom of the visible area */
}

/* Width variants also exist */
.full-dynamic {
  width: 100dvw;
  height: 100dvh;
}

svh is the safe choice when content must never be clipped. lvh is for full-bleed backgrounds. dvh is the general-purpose replacement for vh on mobile. All three are identical on desktop where toolbars do not change size.

Key points

Concepts covered

vw, vh, vmin, vmax, dvh, svh, lvh, Fluid Sizing