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:
| Unit | Name | In CSS pixels |
|---|---|---|
| 1in | inch | 96 px |
| 1cm | centimeter | 37.795 px |
| 1mm | millimeter | 3.78 px |
| 1Q | quarter-millimeter | 0.9449 px |
| 1pt | point (1/72 in) | 1.333 px |
| 1pc | pica (1/6 in) | 16 px |
| 1px | CSS 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:
| rem | At 16px default | At 20px setting |
|---|---|---|
| 0.75rem | 12px | 15px |
| 0.875rem | 14px | 17.5px |
| 1rem | 16px | 20px |
| 1.125rem | 18px | 22.5px |
| 1.25rem | 20px | 25px |
| 1.5rem | 24px | 30px |
| 2rem | 32px | 40px |
| 3rem | 48px | 60px |
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
autowhen that height depends on content. That is whyheight: 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:
| Value | Result |
|---|---|
| 50vw | 640px |
| 100vh | 800px |
| 10vmin | 80px |
| 10vmax | 128px |
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 width | 0.75rem + 1.25vw | Used size |
|---|---|---|
| 320px | 16px | 16px |
| 375px | 16.688px | 16.688px |
| 768px | 21.6px | 21.6px |
| 1024px | 24.8px | 24px |
| 1280px | 28px | 24px |
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-widthin 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
- W3C, CSS Values and Units Module Level 4, Working Draft of 12 March 2024 (absolute units: 1in = 2.54cm = 96px, 1pt = 1/72in, 1pc = 1/6in, 1Q = 1/40cm; em, rem, ex, ch, lh; font-relative units on font-size resolve against the parent; small, large and dynamic viewport units; clamp(MIN, VAL, MAX) equals max(MIN, min(VAL, MAX)) and MIN wins a conflict)
- MDN Web Docs: length (px = 1in / 96 and several device pixels on high-resolution screens; rem and the common 16px default; em on font-size is the inherited size; sv*, lv* and dv* units; default vh currently equals lvh; dynamic units can resize content while scrolling; percentages are not lengths)
- MDN Web Docs: font-size (em values compound: 25.6px and 40.96px in the nested span example; rem avoids compounding; px font sizes are not accessible; prefer values relative to the user's default)
- W3C, CSS 2.2, Box model, sections 8.3 and 8.4 (percentage margins and paddings, including top and bottom, refer to the width of the containing block)
- W3C, CSS 2.2, Visual formatting model details, sections 10.2 and 10.5 (percentage width refers to the containing block width; percentage height to its height, and acts as auto if that height depends on content)