↑↓ to move ↵ to open Esc to close Browse all tools

Developer guide

CSS Units: px, em, rem, %, vw, vh and When to Use Each

CSS has absolute units, which are fixed, and relative units, which follow a font size, a parent box or the browser window. Picking the wrong one is behind text that ignores the reader's settings, menus that grow with every nesting level and full-height sections hidden under a phone's address bar. Here is what each unit is measured against, with conversion tables, and which one to reach for.

Absolute units: everything is px underneath

The CSS Values and Units specification ties all absolute units to one anchor: 1in = 2.54cm = 96px. A CSS pixel is therefore 1/96 of an inch by definition, and the other units follow:

UnitNameIn CSS pixels
1ininch96 px
1cmcentimeter37.795 px
1mmmillimeter3.78 px
1Qquarter-millimeter0.9449 px
1ptpoint (1/72 in)1.333 px
1pcpica (1/6 in)16 px
1pxCSS pixel (1/96 in)1 px

On a screen, these are not physical measurements. MDN explains that on high-resolution screens one CSS pixel spans several device pixels, so a 1cm box is not exactly 1 centimeter on your phone. The physical units are useful in print stylesheets, where a 12pt font is 16px and a 2cm margin is 75.591px. On screens, use px for things that should not scale with text: borders, hairlines, shadows. The guide on points vs pixels covers how design tools map them.

em and rem: relative to text

The specification defines em as the computed font size of the element it is used on, and rem as the em of the root element. One exception matters: used on font-size itself, em refers to the parent's font size. That makes em compound. MDN's example sets nested spans to 1.6em on a 16px base: the outer span renders at 25.6px and the inner one at 40.96px. Switch to 1.6rem and both are 25.6px.

rem follows the root size, and MDN says a common browser default is 16px, which users can change. Here is what common rem values come to at the default and for a reader who set 20px:

remAt 16px defaultAt 20px setting
0.75rem12px15px
0.875rem14px17.5px
1rem16px20px
1.125rem18px22.5px
1.25rem20px25px
1.5rem24px30px
2rem32px40px
3rem48px60px

That second column is the point. MDN warns that font sizes in px are not accessible, because in some browsers users cannot enlarge them, and recommends values relative to the user's default. Size text in rem and the whole page respects the reader's choice. The px to rem converter turns a design's pixel values into rem for any root size.

em still has a place: padding on a button in em grows with the button's own text, so a small and a large button keep the same proportions. Use rem for font sizes and page-level spacing, em for spacing that belongs to one component's text.

ch, ex and lh

Three more font-relative units are worth knowing. ch is measured from the width of the "0" glyph in the current font, which makes max-width: 65ch a quick way to cap a paragraph at roughly that many characters per line. ex is the font's x-height; the specification says to assume 0.5em where it cannot be determined. lh equals the element's computed line height, handy for spacing that lines up with the text rhythm, such as a margin of exactly one line. All three change with the font, so they are best for typography rather than layout.

Percentages: relative to the parent box

MDN notes that percentages are not lengths, and what they refer to depends on the property. CSS 2.2 sets the rules most layouts rely on:

  • width: a percentage of the containing block's width.
  • height: a percentage of the containing block's height, but treated as auto when that height depends on content. That is why height: 50% often does nothing.
  • margin and padding: a percentage of the containing block's width, even for top and bottom. A padding-top: 50% box is half as tall as its parent is wide.

Percent widths suit columns and fluid images. For heights, give the parent an explicit height or use a different unit.

vw, vh and the phone address bar

Viewport units are a percentage of the browser window: 1vw is 1 percent of its width, 1vh 1 percent of its height, vmin the smaller of the two and vmax the larger. On a 1280 by 800 window:

ValueResult
50vw640px
100vh800px
10vmin80px
10vmax128px

Phones complicate vh, because the address bar slides away as you scroll, so the window height changes. The specification added three sets of units for this, and MDN describes them:

  • svh, svw (small): measured with the browser interface expanded. Content always fits, and may leave a gap when the bar hides.
  • lvh, lvw (large): measured with the interface retracted. Content may hide behind the bar when it shows.
  • dvh, dvw (dynamic): follow the bar as it moves. MDN warns this can resize content while the user scrolls and cost performance.

MDN states that the default units, vh and vw, are currently equal to their large counterparts. So height: 100vh is 100lvh, which is why a full-screen hero slips under the address bar. Use 100svh when the content must stay visible, 100dvh for a full-screen app view, and keep vh for decoration.

Fluid sizes with clamp()

The specification defines clamp(MIN, VAL, MAX) as the same value as max(MIN, min(VAL, MAX)): the middle value, kept between a floor and a ceiling. Mixing rem and vw in the middle value gives text that grows with the window but stays readable. For clamp(1rem, 0.75rem + 1.25vw, 1.5rem) at a 16px root:

Window width0.75rem + 1.25vwUsed size
320px16px16px
375px16.688px16.688px
768px21.6px21.6px
1024px24.8px24px
1280px28px24px

Keep a rem part in the middle value. A size made only of vw ignores the reader's font setting completely. If the minimum is larger than the maximum, the specification says the minimum wins. The CSS clamp generator works out the middle value from a minimum and maximum size and the two window widths where they should apply.

Which unit for what

  • Font sizes: rem, or clamp() with a rem floor and ceiling.
  • Spacing around text: rem for page rhythm, em inside a component.
  • Borders, outlines, shadows: px.
  • Column widths: %, with a max-width in rem or ch to keep lines readable.
  • Full-height sections on phones: svh or dvh, not vh.
  • Print stylesheets: pt, cm, mm, in.

For tap areas, see the guide on touch target sizes, and for scaling and contrast rules the WCAG basics.

Frequently asked questions

Should I use px or rem for font sizes?

Use rem. MDN notes that font sizes in px are not accessible because in some browsers the user cannot change them, and recommends values relative to the user's default font size. With rem, a reader who sets 20px as the default gets everything scaled by 1.25, while your layout keeps its proportions.

What is the difference between em and rem?

Both are relative to a font size. 1em is the font size of the element itself, and when used on font-size it is the inherited size from the parent, so nested ems multiply. 1rem is always the font size of the root html element, so it does not compound. MDN's example: two nested spans at 1.6em on a 16px base render at 25.6px and 40.96px; at 1.6rem both are 25.6px.

How many pixels is 1rem?

As many as the root font size. MDN says a common browser default is 16px, so 1rem is usually 16px, 1.5rem is 24px and 0.875rem is 14px. Users can change the default in their browser settings, which is exactly why rem is useful.

Why is 100vh taller than the screen on my phone?

On mobile, the address bar slides in and out. MDN says the default vh unit currently equals lvh, the large viewport, measured with the browser interface retracted. When the bar is visible, an element of 100vh is taller than what you can see. Use 100svh to fit the small viewport, or 100dvh to follow the bar as it moves.

Is a CSS pixel the same as a screen pixel?

Not necessarily. The CSS specification defines 1px as 1/96 of an inch, and MDN explains that on high-resolution screens and printers one CSS pixel covers several device pixels. Physical size on screen therefore varies from device to device.

Sources