Every size you set in CSS — font sizes, widths, margins, gaps — needs a unit attached to it, and which unit you pick changes how that value behaves as the page is resized, zoomed, or viewed on a different device. Picking the wrong unit is one of the most common reasons a layout that looks fine on your screen breaks somewhere else.
CSS units fall into two broad categories: absolute units, which always render at the same physical size regardless of context, and relative units, which scale based on something else — a parent element, the root font size, or the viewport.
Absolute Units: px
The pixel (px) is the only absolute unit you'll use regularly. It's predictable — 16px is always 16px — which makes it great for things that genuinely shouldn't scale, like a 1px border.
.card {
border: 1px solid #ddd;
border-radius: 8px;
}
This renders a card with a crisp, fixed-width border and corner radius that never changes size, no matter what else on the page is resized.
Relative Units: em and rem
Both em and rem are relative to a font size, but to a different one — and mixing them up causes a classic bug.
emis relative to the font size of the current element's parent. If you nest elements that each set a font size in em, the sizes compound.rem("root em") is always relative to the root<html>element's font size, no matter how deeply nested the element is.
html { font-size: 16px; }
.outer { font-size: 1.5em; } /* 1.5 × 16px = 24px */
.outer .inner { font-size: 1.5em; } /* 1.5 × 24px = 36px, NOT 24px! */
.outer .inner-rem { font-size: 1.5rem; } /* always 1.5 × 16px = 24px */
The nested .inner element ends up at 36px because each em multiplies against its parent's already-scaled size — a surprising compounding effect. .inner-rem stays at a predictable 24px regardless of nesting depth, which is why most developers default to rem for font sizes and spacing, reserving em for cases where you deliberately want a value to scale with its immediate parent (like padding inside a button that should grow with the button's own font size).
Percentages and Viewport Units
A percentage (%) is relative to the corresponding property on the parent element — width: 50% means half the parent's width. Viewport units are relative to the browser window itself: vw is 1% of the viewport's width, and vh is 1% of its height.
.hero {
width: 100%;
height: 100vh; /* always fills the full visible browser height */
font-size: 5vw; /* text that scales directly with window width */
}
This hero section always fills the entire visible height of the browser window, and its heading text grows and shrinks fluidly as the window is resized — useful for full-screen landing sections, though vw-based font sizing can swing to extremes on very narrow or very wide screens unless paired with clamp() to set sensible limits.
Which Unit Should You Use?
A practical default: use rem for font sizes and most spacing (margin/padding), % for widths inside a flexible container, px for things that must stay crisp and fixed like borders, and viewport units sparingly for full-screen sections. This combination keeps a layout both predictable and responsive, and pairs naturally with techniques covered in responsive, mobile-first design.
