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.

  • em is 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.