CSSRelative Units (em, rem, %)

Relative Units (em, rem, %)

Relative units scale in relation to something else — a parent's font size, the root font size, or the container's dimensions. They're the key to building layouts and typography that adapt to different screen sizes, user preferences, and content contexts. The three most important are em, rem, and % — each useful for different purposes.

em — relative to the current font size

1em equals the computed font size of the current element. If the element's font size is 18px, 1em is 18px, 0.5em is 9px, and 2em is 36px. For properties other than font-size, em is relative to the element's own font-size. For font-size itself, em is relative to the parent's font-size.

CSS
/* em for font-size — relative to parent's font-size */
body  { font-size: 16px; }
p     { font-size: 1em;   }  /* 16px — same as parent */
small { font-size: 0.875em; } /* 14px — 87.5% of 16px */
h1    { font-size: 2em;   }  /* 32px — twice the parent */

/* em for spacing — relative to the element's OWN font-size */
.heading {
  font-size: 2rem;       /* 32px */
  margin-bottom: 0.5em;  /* 16px — 0.5 × 32px (not 0.5 × root) */
  padding-inline: 1em;   /* 32px — proportional to the heading's own size */
}

/* This means em-based spacing scales with font-size automatically */
em compounds when nested — a component with font-size: 0.9em inside another with font-size: 0.9em results in 0.81em at the inner element, not 0.9em
This compounding is the main pitfall of `em` for font sizes. If you have a list nested inside an article that's `0.9em`, and the list items are also `0.9em`, the list items become `0.81em` — smaller than intended. `rem` avoids this entirely by always being relative to the root, not the current element.
rem — relative to the root font size

1rem always equals the root element's (<html>) font size, regardless of where the element is nested. It doesn't compound. This makes it ideal for font sizes and consistent spacing:

CSS
/* The root font size — typically 16px browser default */
:root { font-size: 16px; }  /* or leave it alone and use the browser default */

/* rem values — always relative to :root */
h1 { font-size: 2rem;    }  /* 32px — always */
h2 { font-size: 1.5rem;  }  /* 24px — always */
h3 { font-size: 1.25rem; }  /* 20px — always */
p  { font-size: 1rem;    }  /* 16px — always */

/* Spacing scale in rem — consistent across the site */
:root {
  --space-1: 0.25rem;   /*  4px */
  --space-2: 0.5rem;    /*  8px */
  --space-3: 0.75rem;   /* 12px */
  --space-4: 1rem;      /* 16px */
  --space-6: 1.5rem;    /* 24px */
  --space-8: 2rem;      /* 32px */
  --space-12: 3rem;     /* 48px */
}

/* rem respects user font size preferences */
/* If user sets browser font size to 20px: */
h1 { font-size: 2rem; } /* → 40px — scales correctly */
rem for font sizes, em for component-local spacing — this is the widely recommended combination that respects user preferences while keeping components self-contained
The practical recommendation: use `rem` for all font sizes (so user preferences are respected and nothing compounds), and use `em` for padding, margin, and gap on components (so they scale proportionally with the component's font size). For example, a button with `font-size: 1rem` and `padding: 0.5em 1.5em` will scale its padding automatically if you change the font size — the padding is defined relative to the text it contains.
% — relative to the parent or context

Percentage values are relative to the parent's value for the same property — for most properties. There are notable exceptions:

CSS
/* Width — % of parent's width */
.column { width: 50%; }      /* half the parent's width */

/* Height — % of parent's HEIGHT (requires parent to have a definite height) */
.full-height { height: 100%; } /* needs parent to have a height set */

/* Font-size — % of parent's font-size (same as em) */
p { font-size: 90%; }  /* 90% of parent's font-size */

/* Margin and padding — ALWAYS % of parent's WIDTH (even for top/bottom!) */
.card { padding: 5%; }  /* 5% of parent's width — all four sides */

/* Line-height — % of element's own font-size */
p { line-height: 160%; } /* 160% of the element's font-size */

/* Transform translate — % of the element's own dimensions */
.center {
  transform: translate(-50%, -50%); /* moves left by 50% of own width, up by 50% of own height */
}
Choosing between em, rem, and %

Use case

Recommended unit

Why

Font sizes

rem

Doesn't compound; respects user preferences

Component padding/margin

em

Scales with the component's font size

Global spacing tokens

rem

Consistent across the whole page

Layout widths

% or viewport units

Relative to container or screen

Border radius

px or %

Fixed (px) or percentage of element size (%)

Line height

Unitless (1.6)

Avoids computed-value inheritance issue

Media query breakpoints

em (preferred) or px

em breakpoints scale with browser text size

CSS
/* A well-structured approach combining all three */
:root {
  font-size: 100%; /* respect browser default (typically 16px) */
}

body {
  font-size: 1rem;        /* 16px — uses root/browser preference */
  line-height: 1.6;       /* unitless */
}

h1 {
  font-size: 2.25rem;     /* always 36px relative to root */
  margin-bottom: 0.5em;   /* 18px — scales if h1 font-size changes */
}

.container {
  max-width: 75rem;       /* 1200px — in rem, scales with user preferences */
  padding-inline: 1.5rem; /* 24px base padding */
  margin-inline: auto;
}

.card {
  padding: 1.5rem;        /* consistent with spacing scale */
  border-radius: 0.5rem;  /* 8px */
}
Next
Units that scale with the browser viewport — for truly responsive layouts: [Viewport Units](/css/viewport-units).