DNAðŸŽĻ CSSCSS Units: Absolute vs Relative
ðŸĢHatchlingCSSUnitsResponsiveFundamentals

CSS Units: Absolute vs Relative

Choosing the right unit is an architecture decision. px for borders, rem for typography, em for component-local scaling, viewport units for full-screen layouts — each serves a specific purpose.

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:

UnitEquivalentUse Case
px1/96th of an inch (1 CSS pixel)Borders, shadows, fine-grained control
cmCentimetersPrint stylesheets
mmMillimetersPrint stylesheets
inInches (= 96px)Print stylesheets
ptPoints (= 1/72 inch = 1.33px)Print typography
pcPicas (= 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)
  • rem respects that setting; px ignores 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

UnitReferenceBehavior
vw1% of viewport widthScales with window width
vh1% of viewport heightScales with window height
vmin1% of smaller viewport dimensionMin of vw/vh
vmax1% of larger viewport dimensionMax of vw/vh
dvhDynamic viewport heightAccounts for mobile browser chrome
svhSmall viewport heightSmallest possible viewport
lvhLarge viewport heightLargest 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);
}
UnitReference
cqw1% of container's width
cqh1% of container's height
cqi1% of container's inline size
cqb1% 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 CaseRecommended UnitWhy
Font sizesremRespects user preferences, no compounding
Spacing (padding/margin)rem or emrem for global, em for component-local
Borders, shadowspxFine-grained, don't need to scale
Media query breakpointsemConsistent across zoom levels
Full-screen sectionsdvh / dvwAccounts for mobile browser chrome
Text container widthchDirectly tied to character count
Component proportionsemScales with the component's font-size
Icons alongside text1emMatches current text size
Line heightUnitless number1.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:

  1. rem vs em — rem for global consistency, em for component-local scaling, awareness of em compounding
  2. Accessibility — rem respects browser font-size settings, px doesn't; why this matters
  3. Viewport units — dvh vs vh on mobile, vmin/vmax for orientation-agnostic layouts
  4. Unitless line-height — Why 1.5 is better than 1.5em or 24px (ratio inheritance)
  5. clamp() fluidity — Building responsive values without media queries, understanding the min + rate × vw formula