Skip to content

CSS Viewport Units: vw, vh, vmin, vmax

Sep 2, 2026 · Web Development

Viewport units size elements as a percentage of the browser viewport rather than of a parent element: 1vw is one percent of viewport width, 1vh is one percent of viewport height, 1vmin is one percent of the smaller dimension, and 1vmax is one percent of the larger. They let you build layouts and type that scale with the window itself, but they also carry two well-known traps — the mobile address-bar problem with vh and the scrollbar problem with vw — that the newer svh, lvh and dvh units were introduced to solve. Knowing exactly what each unit measures is what keeps them from surprising you.

What do vw and vh actually measure?

vw and vh are percentages of the viewport’s width and height, where the viewport is the visible area of the browser window, not the document or any container. This is the crucial distinction from percentage units. A width of 50% is half of the element’s containing block, which could be tiny; a width of 50vw is half of the whole viewport no matter how deeply nested the element is or how small its parent happens to be.

.hero {
  width: 100vw;   /* full viewport width */
  height: 100vh;  /* full viewport height */
}
.callout {
  padding-inline: 5vw;  /* scales with window width */
}

Because they ignore ancestry, viewport units are ideal for full-bleed sections, splash screens, and spacing that should feel proportional to the window. The value updates live as the user resizes, so a 100vh hero always fills the visible height at that instant — which is exactly where the mobile complication begins.

How do vmin and vmax behave?

vmin resolves against the smaller of the two viewport dimensions and vmax against the larger, so the two swap meaning when the device rotates. On a portrait phone the width is the smaller dimension, so vmin tracks width and vmax tracks height. Rotate to landscape and they trade places. This makes them powerful for things that should stay proportional to the “tightest” or “roomiest” axis regardless of orientation.

A common use is sizing something that must always fit on screen. An element at 90vmin square is guaranteed to fit within the shorter side with a 10% margin, in either orientation — perfect for a game board, an image that must never be cropped, or a modal that should stay comfortably inside the visible area.

Unit 1 unit equals 1% of Portrait phone Landscape phone
vw Viewport width The short side The long side
vh Viewport height The long side The short side
vmin Smaller dimension = vw = vh
vmax Larger dimension = vh = vw

Why did 100vh break on mobile browsers?

On many mobile browsers the height that vh measured did not match the space actually visible, because the address bar and toolbars slide in and out as you scroll. To avoid the page reflowing every time the bar moved, browsers historically fixed 100vh to the largest possible viewport — the height with the browser UI retracted. That meant an element set to height: 100vh was taller than the space visible when the address bar was showing, so its bottom slice sat hidden behind or below the bar until you scrolled.

The symptom is familiar: a “full screen” hero or a bottom-pinned button that is partly cut off on a phone, or a page that has a small unexpected scroll even though the content should fit. The layout was technically correct against the definition of vh; the definition just did not match users’ intuition of “the screen.”

What are svh, lvh and dvh?

They are three viewport-height units that describe the small, large and dynamic states of the viewport, giving you explicit control over which height you mean. Instead of one ambiguous vh, you can now say precisely which measurement you want:

Unit Meaning Browser UI state assumed
svh Small viewport height UI expanded (bars visible)
lvh Large viewport height UI retracted (bars hidden)
dvh Dynamic viewport height Updates as the UI shows/hides

If you want content guaranteed to be fully visible even with the address bar showing, use svh: 100svh is the height with the bars present, so nothing hides behind them. If you want a true edge-to-edge fill, lvh matches the tallest state. And dvh tracks the live value, growing and shrinking as the bar animates — useful when you want an element to keep filling the visible area at every moment, at the cost of the element resizing during the scroll gesture.

/* Guaranteed visible even with the mobile browser bar shown */
.sheet { min-height: 100svh; }

/* Fills whatever is visible right now, resizing as bars move */
.stage { height: 100dvh; }

Equivalent width variants (svw, lvw, dvw) and the vmin/vmax variants exist too, though the height ones solve the pain point people hit most often.

Does 100vw cause horizontal scrollbars?

It can, because on some desktop browsers 100vw counts the full viewport width including the area beneath a classic vertical scrollbar, while the content area is narrower. If your page has a vertical scrollbar that takes up, say, 15 real pixels of width, an element set to width: 100vw is 15 pixels wider than the visible content column. The overflow spills past the right edge and the browser adds a horizontal scrollbar — the tell-tale “why is my page scrolling sideways” bug.

The safest fix for full-width elements is often to avoid 100vw in favour of layout that respects the content box, such as letting a block element default to the width of its container, or using width: 100% on an element whose containing block already excludes the scrollbar. Where you genuinely need viewport-relative width, test with a scrollbar present. You can sanity-check the arithmetic behind any of these conversions with a client-side CSS units converter before committing a value, since it computes the pixel equivalents locally in your browser.

When should I reach for viewport units?

Use them when an element should scale with the window rather than with its parent — and pick the specific unit that matches what “the window” means for that case. Reach for vw for full-bleed widths and fluid horizontal spacing, vmin for shapes that must always fit on screen in any orientation, and the svh/lvh/dvh family instead of bare vh whenever mobile browser chrome is in play. Viewport units also pair well with clamp() for fluid typography, where a vw term lets font size grow with the window between a sensible minimum and maximum.

Fluid typography deserves a specific mention because it is where viewport units shine while also causing the most trouble if used raw. Sizing text at font-size: 4vw alone makes it grow without limit on very wide screens and shrink to unreadable on narrow ones. Wrapping the viewport term in clamp() — for example clamp(1rem, 0.5rem + 2vw, 2rem) — bounds the result between a floor and a ceiling while letting it scale fluidly in between, which gives you responsive type without a stack of breakpoints. The rem terms keep the minimum and maximum tied to the user’s font preference, so the technique stays accessible. This combination of a relative floor, a relative ceiling, and a viewport-driven middle is the pattern to reach for rather than a bare viewport unit on its own.

The single habit that prevents most viewport-unit bugs is to say exactly which measurement you mean. Bare vh was ambiguous, and that ambiguity is what produced years of hidden buttons and phantom scrolls. With the small, large and dynamic units now available, you can be explicit — full visibility with svh, true fill with lvh, live tracking with dvh — and let the browser do the right thing on every device.

Frequently asked questions

What does 1vw mean?

1vw is one percent of the viewport width. So 100vw is the full viewport width and 50vw is half of it. vh works the same way against viewport height.

What is the difference between vmin and vmax?

vmin is one percent of whichever viewport dimension is smaller (width or height), and vmax is one percent of the larger dimension. They swap roles when you rotate the device between portrait and landscape.

Why did 100vh cause problems on mobile?

On many mobile browsers 100vh referred to the tallest possible viewport, ignoring the address bar that overlaps the page. Content sized to 100vh could be partly hidden behind the bar until the user scrolled.

What do svh, lvh and dvh mean?

svh is the small viewport height (browser UI expanded), lvh is the large viewport height (UI retracted), and dvh is the dynamic viewport height that updates as the UI shows and hides.

Does 100vw include the scrollbar?

On some desktop browsers 100vw includes the space under a classic vertical scrollbar, so an element at 100vw can be slightly wider than the visible content area and cause horizontal overflow.