A hero sized at 100vh looks right in every desktop screenshot and wrong in every pocket browser, because vh always measures the largest viewport, not the one you are looking at. The three-prefix family closes that gap, and the patch is impressively dull to read.

/* small: never taller than what is visible, bars included */
.hero { min-height: 100svh; }
/* dynamic: tracks the bars as they hide and return */
.photo-fill { height: 100dvh; }

The money case: mobile browser bars

  • On mobile, 100vh measures the largest possible viewport, so a full-height hero sits partly behind the bottom bar until the user starts scrolling, a genuinely awful first impression.
  • 100svh uses the small viewport, the state where both bars are visible; anything sized with it is fully visible on load, no scrolling required, no surprise.
  • 100dvh follows the bars live. It is honest, but each change causes reflow mid-scroll, so keep it out of height-critical stacks and prefer it for photo fills that should cover whatever is visible.

Desktop sees nothing

On desktop browsers the three variants usually compute to the same number, so a laptop review will not catch the defect; it only shows on devices with dynamic bars, which is exactly where most first visits happen. Responsive design mode with a touch viewport covers the check in seconds.

The boring summary: full sections get 100svh, immersive overlays get 100dvh, and 100vh stays a desktop-only afterthought. An gacor trick, not because it is clever, but because three letters replace a stack of scrollbar sniffing once and for all.