Key takeaways
- Use
remfor font sizes so text respects user settings;pxfor borders and fine details. %,frand viewport units (vw,dvh) handle fluid layouts.clamp()creates fluid sizes with sensible minimums and maximums — often replacing several media queries.
CSS has more than a dozen length units, and choosing the wrong one causes real problems: text that ignores a visitor’s font-size preference, full-screen sections that jump on mobile, or padding that’s huge on desktop and cramped on phones. Here’s what each unit is for.
Absolute vs relative units#
| Unit | Relative to | Best for |
|---|---|---|
px |
CSS pixel (not device pixel) | Borders, shadows, small fixed details |
rem |
Root (html) font size, usually 16 px |
Font sizes, spacing scales |
em |
Current element’s font size | Padding that scales with its text (buttons), icon sizes |
% |
Parent’s size (varies by property) | Widths inside containers |
vw / vh |
1% of viewport width / height | Fluid type, full-width sections |
dvh / svh / lvh |
Dynamic / small / large viewport height | Full-height mobile sections |
ch |
Width of the “0” character | Readable line lengths: max-width: 70ch |
fr |
Fraction of free space (Grid only) | Grid columns |
cqi |
1% of the container’s inline size | Container-query components |
Why rem for font sizes?#
Some people increase their browser’s default font size because they need larger text. If you set font-size: 14px, you override that choice. With font-size: 0.875rem, text scales with their preference. That’s an accessibility win at no cost.
em: useful but compounding#
em is relative to the element’s own font size, which itself may be relative to its parent. Nested em sizes compound (0.8em inside 0.8em = 0.64 of the original). Use em deliberately — for example, button padding of 0.75em 1.25em stays proportional whether the button text is small or large.
Need a hand with this?
Get a quick, honest review of your website’s SEO.
The 100vh problem on mobile#
On phones, browser toolbars appear and disappear while scrolling. 100vh uses the largest height, so full-screen sections get cut off behind the toolbar. Use the newer units:
.hero { min-height: 100svh; } /* fits with toolbars visible */
.app { height: 100dvh; } /* adjusts as toolbars change */
clamp(): fluid sizes with limits#
h1 { font-size: clamp(2rem, 1.2rem + 3vw, 3.5rem); }
.section { padding-block: clamp(40px, 7vw, 96px); }
.wrap { width: min(100% - 32px, 1200px); margin-inline: auto; }
clamp(min, preferred, max)— never smaller than min, never larger than max, fluid in between.- Mixing
remwithvwin the preferred value keeps text zoomable (purevwtext doesn’t scale with browser zoom — an accessibility issue). min()andmax()handle simpler cases.
A practical default system#
- Body text:
1rem–1.125rem, line-height 1.6–1.8 (unitless). - Headings:
clamp()with rem + vw. - Spacing: a small scale in rem or px (4, 8, 12, 16, 24, 32, 48…).
- Layout widths:
%,fr,min()andchfor text. - Borders and hairlines:
px.
CSS units FAQ#
Is px bad?#
No. CSS pixels scale with device density and zoom. Just avoid px for font sizes if you want to respect user font settings.
Should line-height have units?#
Use a unitless number like 1.6; it scales correctly for nested elements with different font sizes.
What is a CSS pixel on retina screens?#
A CSS pixel can map to 2, 3 or more device pixels. That’s why images need higher-resolution versions via srcset.