CSS Units Explained: px, em, rem, %, vw, and When to Use Each
CSS gives you a dozen ways to express a length, and choosing the wrong one is behind a surprising number of layout bugs, broken zoom, and text that will not scale for people who need it larger. This guide sorts the units into the few you will actually use, explains how each one calculates its value, and gives a clear rule for when to reach for each.
Once you are comfortable with units, two tools on this site put them to work: the Box Shadow Generator → uses pixel offsets and blur, and the Viewport Meta Generator → sets up the viewport that makes viewport units behave.
Absolute versus relative
Every length unit is either absolute or relative. An absolute unit is a fixed size that does not change based on context. A relative unit calculates its value from something else: the font size of an element, the size of the viewport, or the dimensions of a parent. Relative units are what make a layout flexible, so most modern CSS leans on them.
The pixel
The px unit is the absolute unit you will meet first. One CSS pixel is a
fixed reference size, not necessarily one device pixel, which is why designs look
consistent across screens of different densities. Pixels are predictable and precise, which
makes them ideal for things that should not scale: borders, box shadows, and small
fixed details.
.card {
border: 1px solid #ccc;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
The trap with pixels is using them for font sizes. A font set in pixels ignores the user's browser font preference, which is a real accessibility problem for anyone who has bumped up their default text size.
em and rem
These two relative units are based on font size, and the difference between them is the single most useful thing to understand in this whole topic.
rem is relative to the root font size, the size set on
the html element, which defaults to 16 pixels. 1rem is therefore 16 pixels by
default, 1.5rem is 24 pixels, and so on. Because every rem points at the same
root, the math stays predictable no matter how deep you nest.
em is relative to the font size of the current element. That makes it powerful for component spacing that should scale with its own text, but it also compounds when you nest, which surprises people.
html { font-size: 16px; }
.parent { font-size: 1.5em; } /* 24px */
.parent .child { font-size: 1.5em; } /* 36px, not 24px */
The practical rule: use rem for font sizes so text respects the user's preference and stays predictable, and use em for padding or margin inside a component when you want that spacing to grow with the component's own font.
Tip: Setting font sizes in rem is the easiest accessibility win in CSS. When a user raises their browser default from 16 to 20 pixels, every rem based size scales with it automatically. Pixel based text ignores them entirely.
Percentages
The % unit is relative to the parent, but what it is a percent of
depends on the property. Width is a percent of the parent's width, height of the parent's
height, and padding, perhaps surprisingly, is always a percent of the parent's
width even on the top and bottom. Percentages shine for fluid widths in
layouts where an element should take a share of its container.
Viewport units
Viewport units measure against the browser window itself. 1vw is one percent
of the viewport width and 1vh is one percent of the height. vmin
and vmax track the smaller or larger of the two. These are excellent for full
height hero sections and for typography that scales with the screen.
| Unit | Relative to | Best for |
|---|---|---|
| px | Fixed reference | Borders, shadows, hairlines |
| rem | Root font size | Font sizes, consistent spacing |
| em | Element font size | Component internal padding |
| % | Parent dimension | Fluid widths |
| vw / vh | Viewport size | Hero sections, fluid type |
clamp ties it together
Modern CSS lets you combine units with clamp(), which takes a minimum, a
preferred value, and a maximum. This is the cleanest way to build fluid typography that
never gets too small or too large.
h1 {
font-size: clamp(1.75rem, 4vw + 1rem, 3rem);
}
Here the heading scales with the viewport through the 4vw term but is locked
between 1.75rem and 3rem, so it stays readable on a phone and never
becomes absurd on a wide monitor.
A simple decision guide
Reach for rem by default for font sizes. Use px for borders and shadows and any detail that must stay crisp and fixed. Use percent for fluid widths inside a container. Use vw and vh for things that should track the window. And use clamp when you want a value to flex within sensible bounds.
Related reading
See units applied to real effects in the CSS box shadow guide, and keep your text readable at any size with the color contrast and accessibility guide.
Bottom line
You do not need all dozen CSS units. Master rem for type, px for fine fixed details, percent for fluid layout, and viewport units for screen relative sizing, then layer in clamp for the polish. Put them into practice with the Box Shadow Generator → and set up your page correctly with the Viewport Meta Generator →.