CSS has more than a dozen different units for expressing size and distance. Choosing the wrong one does not always break your layout immediately — but it leads to accessibility problems, scaling issues, and maintenance headaches down the road.
This guide covers every unit you are likely to encounter, what it is relative to, and when to actually use it.
Quick reference
| Unit | Relative to | Best used for |
|---|---|---|
| px | Device pixels (fixed) | Borders, shadows, fixed elements |
| rem | Root (html) font size | Font sizes, spacing, layout |
| em | Parent element font size | Component-scoped spacing |
| % | Parent element dimension | Fluid widths, heights |
| vw | 1% of viewport width | Full-width sections, fluid type |
| vh | 1% of viewport height | Full-height sections |
| vmin | 1% of smaller viewport dimension | Responsive square elements |
| vmax | 1% of larger viewport dimension | Rare edge cases |
| ch | Width of the "0" character | Readable text line lengths |
| ex | Height of lowercase "x" | Rarely used in practice |
| svh/dvh/lvh | Viewport height variants | Mobile-safe full-height layouts |
Absolute units — px
px is the most straightforward unit. On standard screens, 1px equals one device pixel. On high-density (retina) screens, the browser scales this so 1 CSS pixel actually spans multiple physical pixels — but you do not need to worry about this.
Use px for: borders (border: 1px solid), box shadows, and anything that should stay a fixed size regardless of font scaling.
Avoid px for: font sizes and spacing in your design system, because px values override the user's browser font size preference and hurt accessibility.
Font-relative units — rem and em
rem (root em)
Always relative to the <html> element's font size. Browser default is 16px, so 1rem = 16px unless you change it.
html { font-size: 62.5%; } /* = 10px, makes math easier */ h1 { font-size: 3.2rem; } /* = 32px */ p { font-size: 1.6rem; } /* = 16px */ .gap { padding: 2.4rem; } /* = 24px */
rem is the right default for font sizes and spacing in most projects. It respects browser preferences and lets you scale the entire UI by changing one root value.
em
Relative to the font size of the current element's parent. This makes it useful for component-scoped spacing but dangerous in nested structures where values compound.
.button { font-size: 1rem; /* = 16px */ padding: 0.75em 1.5em; /* relative to button's own font-size */ } /* If you change font-size, padding scales with it automatically */ .button.small { font-size: 0.875rem; /* padding still proportional — no need to override */ }
Rule of thumb: Use rem for font sizes. Use em for padding and margin inside a component when you want the spacing to scale with the component's own font size.
Percentage — %
Percentage is relative to the parent element. For widths, it means a percentage of the parent's width. For heights, it means a percentage of the parent's height — but only if the parent has a defined height.
.container { width: 100%; } /* fills parent width */ .sidebar { width: 30%; } /* 30% of parent */ .full-page { height: 100%; } /* only works if parent has defined height */
Viewport units — vw, vh, vmin, vmax
Viewport units are relative to the browser window size, not any parent element.
100vw= full width of the viewport100vh= full height of the viewport1vw= 1% of viewport width
.hero { width: 100vw; height: 100vh; /* full screen section */ } /* Fluid typography — scales with viewport width */ h1 { font-size: clamp(2rem, 5vw, 4rem); }
The mobile vh problem
On mobile browsers, 100vh includes the browser toolbar area, causing content to be cut off. The newer units svh (small viewport height) and dvh (dynamic viewport height) solve this:
.hero { /* svh = height excluding mobile browser UI */ min-height: 100svh; }
The ch unit — best for readable text
ch equals the width of the 0 character in the current font. It is the most practical unit for controlling line length, since readability research consistently shows that 60–75 characters per line is optimal for body text.
.article-body { max-width: 65ch; /* ~65 characters wide — ideal for reading */ }
Which unit to use where
- Font sizes → rem
- Spacing (padding, margin, gap) → rem (or em inside self-contained components)
- Layout widths → % or vw with max-width in rem
- Full-screen sections → 100svh or 100dvh
- Borders, shadows → px
- Readable text containers → ch
- Fluid typography → clamp() with rem and vw
Convert px values to rem instantly
Stop doing the division manually. Our PX to REM converter handles single values and bulk conversion with custom base font sizes.
Open PX to REM Converter →