CSS units convert.
Type a value in any unit, get every other unit at your specified base font size and viewport. The conversions you stop doing in your head once your design system grows past three breakpoints.
| px | 16.00px | |
|---|---|---|
| rem | 1.0000rem | |
| em | 1.0000em | |
| % | 100.00% | |
| pt | 12.00pt | |
| pc | 1.000pc | |
| in | 0.1667in | |
| cm | 0.423cm | |
| mm | 4.23mm | |
| vw | 1.250vw | |
| vh | 2.000vh |
Each unit, a different job.
CSS exposes more length units than any sane design system needs, but each one earns its place in some context. px is the workhorse for borders, dividers, and other small fixed details that should never scale with user preferences. rem is the workhorse for everything else — paddings, margins, font sizes, gap widths — because it scales with the user's chosen root font size. Users who set their browser to 20px get a proportionally larger interface; users on small screens with 14px get a proportionally smaller one. Using rem instead of px for layout is the single most effective accessibility win in CSS.
em sounds similar to rem but compounds. A list inside a list inside a list, each at font-size: 0.9em, ends up at 0.729em of the outermost — usually not what you want. Use em only for spacing inside a single component that should scale with its own font size (a button's horizontal padding can sensibly be 0.5em so it grows with its text). For everything else, prefer rem.
% resolves against different things depending on the property. width: 50% is half of the parent's width; font-size: 150% is 1.5× the parent's font size; line-height: 150% is 1.5× the element's own font size; padding: 5% is 5% of the parent's width, even on the top and bottom. The implicit reference point is one of CSS's longest-running confusions; check the spec for the property in question.
vw / vh let layouts respond to viewport size without media queries. font-size: clamp(1rem, 2vw, 2rem) is fluid typography in one declaration. The catch is that on iOS Safari, the address bar shrinks as the user scrolls, which changes vh mid-page and produces visible jumps. The new dynamic viewport units (dvh, svh, lvh) handle this correctly: svh is the smallest viewport (with all UI chrome visible), lvh is the largest, dvh updates dynamically. Use dvh for full-height heroes; use svh for content that must remain visible regardless of chrome.
pt, pc, in, cm, mm are physical units. They are nominally 96 px = 1 inch, regardless of actual screen DPI, which makes them useless for screens (the user can be 6 inches from a phone or 30 inches from a 32-inch monitor; "1 inch" of CSS means nothing at either distance). Reserve them for print stylesheets where the rendering engine actually knows the physical page size. pt is widely used in print contexts because designers raised on print typography think in points; 12pt = 16px in CSS terms.