T
ToolBox
Back to Blog
5 min readToolBox Team

CSS Units Explained: px vs rem vs em vs vw

tutorialcssweb-development

The CSS Units Problem

You are styling a heading and you type `font-size: 24px`. It looks great on your monitor. Then you check it on a phone and it is either too big or too small. A teammate changes the base font size and suddenly half the spacing is off.

CSS has over a dozen units, and picking the right one is not just about personal preference — it directly affects responsiveness, accessibility, and maintainability. Let us go through the ones that matter.

Absolute Units: px

Pixels (`px`) are the simplest CSS unit. One `px` is one device pixel (sort of — high-DPI screens complicate this, but CSS handles the math for you).

```css

.button {

padding: 12px 24px;

border: 1px solid #ccc;

border-radius: 4px;

}

```

When to use px:

- Borders and outlines (you almost always want a consistent 1px or 2px line)

- Box shadows

- Small, fixed-size decorative elements

- When you need pixel-perfect precision

When to avoid px:

- Font sizes (breaks user accessibility settings)

- Spacing and layout in responsive designs

- Anything that should scale with user preferences

Relative Units: rem

`rem` stands for "root em" and is relative to the root element's font size. By default, browsers set the root font size to 16px, so `1rem = 16px`.

```css

html {

font-size: 16px; /* default */

}

h1 {

font-size: 2rem; /* 32px */

margin-bottom: 1rem; /* 16px */

}

p {

font-size: 1rem; /* 16px */

line-height: 1.5rem; /* 24px */

}

```

Why rem is usually the best choice for font sizes:

When a user sets their browser's default font size to 20px (common for users with low vision), all your `rem` values scale proportionally. If you used `px`, those preferences are ignored and your site becomes an accessibility problem.

```css

/* Good: respects user preferences */

.body-text { font-size: 1rem; }

/* Bad: ignores user preferences */

.body-text { font-size: 16px; }

```

Pro tip: Many developers set the root font size to 62.5% so that 1rem = 10px, making mental math easier:

```css

html { font-size: 62.5%; }

/* Now: 1rem = 10px, 1.6rem = 16px, 2.4rem = 24px */

```

Relative Units: em

`em` is relative to the font size of the parent element (or the element itself for font-size properties). This makes it useful for components that should scale proportionally.

```css

.card {

font-size: 1rem; /* 16px base */

padding: 1.5em; /* 24px — relative to this element's font size */

}

.card--large {

font-size: 1.25rem; /* 20px base */

padding: 1.5em; /* 30px — scales with the larger font */

}

```

When to use em:

- Padding and margins within a component that should scale with its own font size

- Media query breakpoints (em-based breakpoints handle zoom better)

- Icon sizing next to text

The compounding problem:

`em` values compound when nested. If a parent has `font-size: 1.2em` and a child also has `font-size: 1.2em`, the child's computed size is 1.44em of the grandparent. This is why `rem` is generally safer for font sizes — it always references the root.

```css

/* Danger: compounding */

.parent { font-size: 1.2em; } /* 19.2px if root is 16px */

.child { font-size: 1.2em; } /* 23.04px — probably not what you wanted */

```

Viewport Units: vw and vh

`vw` and `vh` are percentages of the viewport width and height. `1vw` = 1% of the viewport width.

```css

.hero {

height: 100vh; /* full viewport height */

padding: 5vw; /* scales with viewport width */

}

.hero-title {

font-size: clamp(2rem, 5vw, 4rem); /* responsive font size with limits */

}

```

When to use viewport units:

- Full-screen hero sections (`100vh`)

- Fluid typography that scales with screen size

- Layout elements that should be a proportion of the screen

Watch out for mobile:

On mobile browsers, `100vh` can be taller than the visible area because the address bar is part of the viewport calculation. The newer `dvh` (dynamic viewport height) unit fixes this:

```css

.hero {

height: 100dvh; /* accounts for mobile browser chrome */

}

```

Percentages

Percentages are relative to the parent element's size. They are fundamental for fluid layouts.

```css

.container {

max-width: 1200px;

width: 90%; /* 90% of parent, up to 1200px */

margin: 0 auto;

}

.sidebar {

width: 30%; /* 30% of parent container */

}

```

Which Unit When? A Cheat Sheet

| Use Case | Recommended Unit |

|--------------------------|-----------------|

| Font sizes | rem |

| Component internal spacing| em |

| Layout spacing (margins) | rem |

| Borders & shadows | px |

| Container widths | %, max-width in px/rem |

| Full-screen sections | vh / dvh |

| Fluid typography | clamp(rem, vw, rem) |

| Media queries | em |

The Modern Approach: clamp()

The `clamp()` function is a game changer for responsive design. It sets a minimum, preferred, and maximum value in one line:

```css

/* Font scales fluidly between 1rem and 3rem based on viewport */

h1 {

font-size: clamp(1.5rem, 4vw, 3rem);

}

/* Container padding that adapts to screen size */

.section {

padding: clamp(1rem, 3vw, 3rem);

}

```

This replaces a bunch of media queries with a single, elegant declaration.

Convert Between Units with ToolBox

When you are refactoring a codebase from `px` to `rem`, or need to quickly check what `2.5rem` equals in pixels at a given base size, manual math slows you down.

The [CSS Units Converter](/tools/css-units-converter) on ToolBox lets you:

- Convert between px, rem, em, vw, vh, and percentages instantly

- Set your base font size and viewport dimensions for accurate results

- See all conversions update in real time as you type

It is one of those tools you did not know you needed until you are knee-deep in a responsive redesign. No signup, runs in your browser, free forever.

Want to see more tools and features?