CSS Units: Absolute vs Relative
The unit you choose affects responsiveness, accessibility, and maintainability. Senior engineers don't just pick px or rem by habit â they understand why each unit exists and which problems it solves.
Absolute Units
Absolute units have a fixed size regardless of context:
| Unit | Equivalent | Use Case |
|---|---|---|
px | 1/96th of an inch (1 CSS pixel) | Borders, shadows, fine-grained control |
cm | Centimeters | Print stylesheets |
mm | Millimeters | Print stylesheets |
in | Inches (= 96px) | Print stylesheets |
pt | Points (= 1/72 inch = 1.33px) | Print typography |
pc | Picas (= 12pt = 16px) | Print typography |
In practice, px is the only absolute unit used for screen. But even px is relative on high-DPI screens â 1px in CSS may map to 2 or 3 physical pixels.
.button {
border: 1px solid #ccc; /* Borders: px is fine â 1px is the thinnest visible line */
box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* Shadows: px for consistency */
}Relative Units
rem â Relative to Root
html { font-size: 16px; } /* Browser default */
h1 { font-size: 2rem; } /* 32px (2 Ã 16) */
p { font-size: 1rem; } /* 16px */rem is always relative to the root (<html>) font size. This makes it predictable â changing a parent's font-size won't cascade unpredictably.
Why rem for typography and spacing:
- Users can change browser default font size (accessibility)
remrespects that setting;pxignores it- Creates a consistent scale across the entire site
:root {
--space-xs: 0.25rem; /* 4px */
--space-sm: 0.5rem; /* 8px */
--space-md: 1rem; /* 16px */
--space-lg: 1.5rem; /* 24px */
--space-xl: 2rem; /* 32px */
}em â Relative to Parent/Element Font Size
.parent {
font-size: 20px;
}
.child {
font-size: 0.8em; /* 16px (0.8 Ã 20) */
padding: 1em; /* 16px (1 Ã current font-size of .child) */
margin-bottom: 1.5em; /* 24px (1.5 Ã 16) */
}Key distinction: For font-size, em is relative to the parent's font-size. For other properties (padding, margin, width), em is relative to the element's own computed font-size.
The em compounding trap:
.list { font-size: 0.9em; } /* 14.4px (0.9 Ã 16) */
.list li { font-size: 0.9em; } /* 12.96px (0.9 Ã 14.4) â nested em compounds! */Use rem to avoid this compounding. Use em only when you intentionally want sizing relative to the component's own font-size (e.g., padding that scales with text).
em Best Use Case: Component-Local Scaling
.button {
font-size: 1rem;
padding: 0.5em 1em; /* Scales proportionally with text */
border-radius: 0.25em;
}
.button--small { font-size: 0.875rem; } /* padding/radius scale down */
.button--large { font-size: 1.25rem; } /* padding/radius scale up */Changing only font-size scales the entire button proportionally.
Viewport Units
| Unit | Reference | Behavior |
|---|---|---|
vw | 1% of viewport width | Scales with window width |
vh | 1% of viewport height | Scales with window height |
vmin | 1% of smaller viewport dimension | Min of vw/vh |
vmax | 1% of larger viewport dimension | Max of vw/vh |
dvh | Dynamic viewport height | Accounts for mobile browser chrome |
svh | Small viewport height | Smallest possible viewport |
lvh | Large viewport height | Largest possible viewport |
/* Full-screen hero */
.hero {
min-height: 100dvh; /* Dynamic â adjusts when mobile toolbar appears/hides */
}
/* The mobile 100vh problem */
.hero-broken {
height: 100vh; /* On mobile, extends behind browser toolbar */
}
.hero-fixed {
height: 100dvh; /* Correctly accounts for toolbar */
}% â Relative to Parent
.parent { width: 600px; }
.child { width: 50%; } /* 300px */
/* For padding/margin, % is relative to parent's WIDTH (even for top/bottom) */
.child {
padding-top: 10%; /* 60px (10% of parent's 600px WIDTH, not height) */
margin-bottom: 5%; /* 30px (5% of parent's WIDTH) */
}The "padding percentage is relative to width" behavior is what enables the aspect-ratio hack:
/* Before aspect-ratio property existed */
.aspect-16-9 {
width: 100%;
padding-bottom: 56.25%; /* 9/16 Ã 100% */
height: 0;
}
/* Modern approach */
.aspect-16-9 {
aspect-ratio: 16 / 9;
}Container Query Units
.parent { container-type: inline-size; }
.child {
font-size: clamp(1rem, 3cqi, 1.5rem);
}| Unit | Reference |
|---|---|
cqw | 1% of container's width |
cqh | 1% of container's height |
cqi | 1% of container's inline size |
cqb | 1% of container's block size |
ch and ex
.prose {
max-width: 65ch; /* ~65 characters wide â optimal reading length */
}
/* ch = width of the "0" character */
/* ex = height of the "x" character */ch is ideal for constraining text width because it's directly tied to character count.
When to Use Which Unit
| Use Case | Recommended Unit | Why |
|---|---|---|
| Font sizes | rem | Respects user preferences, no compounding |
| Spacing (padding/margin) | rem or em | rem for global, em for component-local |
| Borders, shadows | px | Fine-grained, don't need to scale |
| Media query breakpoints | em | Consistent across zoom levels |
| Full-screen sections | dvh / dvw | Accounts for mobile browser chrome |
| Text container width | ch | Directly tied to character count |
| Component proportions | em | Scales with the component's font-size |
| Icons alongside text | 1em | Matches current text size |
| Line height | Unitless number | 1.5 not 1.5em â unitless inherits correctly |
Line Height: Unitless vs Unit
/* BAD: em-based line-height */
.parent {
font-size: 20px;
line-height: 1.5em; /* Computed: 30px â this EXACT VALUE inherits */
}
.child {
font-size: 14px;
/* line-height: 30px (inherited computed value) â too much spacing */
}
/* GOOD: unitless line-height */
.parent {
font-size: 20px;
line-height: 1.5; /* The RATIO inherits, not the computed value */
}
.child {
font-size: 14px;
/* line-height: 1.5 Ã 14 = 21px â proportionally correct */
}The clamp() Function
clamp(minimum, preferred, maximum) creates fluid values:
h1 {
font-size: clamp(1.5rem, 1rem + 2vw, 3rem);
/*
At narrow viewports: 1.5rem (minimum)
At wide viewports: 3rem (maximum)
In between: 1rem + 2vw (fluid scaling)
*/
}
.container {
width: clamp(320px, 90%, 1200px);
padding: clamp(1rem, 3vw, 3rem);
}Interview Signal
Senior candidates demonstrate:
remvsemâremfor global consistency,emfor component-local scaling, awareness ofemcompounding- Accessibility â
remrespects browser font-size settings,pxdoesn't; why this matters - Viewport units â
dvhvsvhon mobile,vmin/vmaxfor orientation-agnostic layouts - Unitless line-height â Why
1.5is better than1.5emor24px(ratio inheritance) clamp()fluidity â Building responsive values without media queries, understanding themin + rate à vwformula