HTML, CSS & the Browser

Viewport Units

Definition

There are four classic units. vw and vh are one per cent of the viewport width and height; vmin and vmax track whichever of the two is smaller or larger. Unlike a percentage, they ignore the parent element — height: 100vh is full screen height whatever it sits inside, whereas height: 100% only works if every ancestor has a height. They turn up as full-height hero sections and as spacing that grows on large screens, and they mix with fixed lengths through calc(), as in height: calc(100vh - 64px) to leave room for a header. They are not a substitute for a breakpoint: they scale smoothly with the window rather than switching a layout at a chosen width.

Why It Matters

The problem people actually hit is vh on a phone. Mobile browsers show and hide the address bar as you scroll, so the visible area changes by roughly 60 to 100 pixels, but 100vh is deliberately fixed to the larger measurement. A section set to 100vh is therefore taller than the screen when the bar is showing: a button pinned to the bottom sits below the fold, and the page scrolls by a hair when it should not. The newer units exist for this: dvh is the dynamic height, changing as the bar appears and disappears; svh is the small height, measured with the bar showing; lvh is the large height, with it hidden. Using 100dvh, or 100svh where nothing should ever be cut off, removes the problem outright.

How It Works

The browser resolves viewport units against the layout viewport, recomputing on resize and on orientation change. The classic vh is pinned to the largest viewport, matching lvh, so it does not reflow while the address bar animates — stability was the trade-off and cut-off content is the price. The dynamic units work in current Chrome, Safari, Firefox and Edge; for anything older, write the fallback first and the newer unit after, since a browser that cannot parse height: 100dvh simply keeps the height: 100vh above it. One more trap: vw counts the vertical scrollbar, so width: 100vw on a scrolling page is a few pixels wider than the content area and adds a horizontal scrollbar. Use width: 100% for full-width blocks and keep vw for cases where the overflow is intended.

Real-World Example

A digital invitation at wren-and-sam.99helpers.site puts the date and the RSVP button in a hero styled height: 100vh. On an iPhone with the address bar showing, the button sits just under the fold and half the guests never see it without scrolling. Changing the declaration to 100dvh, with 100vh left above as the fallback, brings the button on screen at every stage of scrolling and needs no JavaScript.

Common Mistakes

  • Using 100vh for a mobile hero and pinning something important to its bottom — the address bar makes the real viewport shorter, so that element starts out below the fold
  • Setting width: 100vw on a page that scrolls vertically — vw counts the scrollbar, so the element is a few pixels wider than the viewport and adds a horizontal scrollbar
  • Sizing body text in vw alone — the text becomes unreadable at one end of the range or the other, where clamp() with a rem minimum and maximum keeps it sane

Related Terms

Put a file online in seconds

Drop in a document, an image, a page or a whole static website and share the link — free, with no build step and no server to set up.

Host a file free →