CSS Units & Values

โ–ถ Try It Yourself

Every dimension in CSS requires a unit. The unit you choose determines whether your layout is rigid or responsive, whether it honors a user’s accessibility settings, and how it behaves across screen sizes. In this lesson you will master the full range of CSS length units and learn to use clamp() for truly fluid layouts.

Absolute vs Relative Units

Unit Type Relative To
px Absolute CSS device-independent pixel
rem Relative Root html element font-size
em Relative Current element’s own font-size
% Relative Parent’s same dimension
vw Viewport 1% of viewport width
vh Viewport 1% of viewport height
ch Relative Width of “0” glyph in current font

When to Use Each Unit

Unit Best For Avoid For
rem Font sizes and global spacing โ€” no compounding, scales with browser prefs Fine pixel-level details
em Component-local padding/margin that should scale with its own font size font-size on nested elements (compounds)
px Borders, shadows, fine 1px details Font sizes (breaks accessibility)
vw/vh Hero sections, full-screen layouts Font sizes alone (use with clamp)

clamp() Function

Syntax Argument Meaning
clamp(min, val, max) min Never smaller than this
val Preferred (fluid) value โ€” usually viewport-based
max Never larger than this
Note: Browsers default to 16px root font size, so 1rem = 16px, 1.5rem = 24px, 0.875rem = 14px. If a user increases their browser base font size, rem values scale automatically. Fixed px values do not โ€” a significant accessibility concern.
Tip: Use rem for font sizes, em for component-level padding (buttons), and px only for fine details that truly must not scale (1px borders). This mental model covers 90% of real-world use cases.
Warning: Avoid using em for font-size on nested elements โ€” it compounds. A parent at 1.25em and a child at 1.25em gives the child 1.5625em of root (1.25 ร— 1.25). Use rem for all font sizes to prevent this cascade.

Basic Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>CSS Units Demo</title>
  <style>
    :root { font-size: 16px; }

    body {
      font-family: system-ui, sans-serif;
      padding: 2rem;
      max-width: 65ch;
      margin: 0 auto;
    }

    h1 { font-size: 2.5rem; margin-bottom: 0.5em; }
    h2 { font-size: 1.75rem; margin-bottom: 0.4em; }

    /* Viewport units for hero */
    .hero {
      height: 50vh;
      background: #1e293b;
      color: white;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: clamp(1.25rem, 4vw, 3rem);
      text-align: center;
      padding: 1rem;
    }

    /* Percentage width */
    .two-col { display: flex; gap: 1.5rem; }
    .main    { width: 70%; }
    .sidebar { width: 30%; min-width: 200px; }

    /* em padding scales with button font-size */
    .btn {
      display: inline-block;
      padding: 0.6em 1.4em;
      font-size: 0.9rem;
      background: #4f46e5;
      color: white;
      border-radius: 0.375rem;
      border: none;
      cursor: pointer;
    }
    .btn-lg { font-size: 1.125rem; }
  </style>
</head>
<body>
  <div class="hero">Fluid Heading โ€” resize the window!</div>
  <h1>CSS Units</h1>
  <p>This text is constrained to 65ch for optimal readability.</p>
  <button class="btn">Normal Button</button>
  <button class="btn btn-lg">Large Button</button>
</body>
</html>

How It Works

Step 1 โ€” Root Font Size Anchors rem

:root { font-size: 16px; } means 1rem = 16px. When a user sets their browser to 20px, all rem values scale proportionally โ€” preserving the site’s intended proportions at the user’s preferred size.

Step 2 โ€” em Inherits from Current Element

h1 has font-size: 2.5rem (40px) and margin-bottom: 0.5em. The em resolves against h1’s own size: 0.5 ร— 40px = 20px โ€” always proportional to the heading.

Step 3 โ€” Viewport Units Fill the Screen

height: 50vh is always half the viewport height โ€” 450px on a 900px screen, 600px on a 1200px screen. Updates in real time on resize.

Step 4 โ€” clamp() Creates Fluid Values

clamp(1.25rem, 4vw, 3rem): never below 1.25rem, never above 3rem, preferably 4vw. At 800px viewport, 4vw = 32px โ€” between bounds, so it wins. Smooth scaling with no media queries.

Step 5 โ€” em Button Padding Scales with Font Size

Adding .btn-lg increases font-size from 0.9rem to 1.125rem. The em padding auto-scales proportionally โ€” no separate padding overrides needed.

Real-World Example: Fluid Typography System

/* typography-system.css */
:root {
  font-size: 100%;

  --text-xs:   clamp(0.70rem,  0.65rem + 0.25vw, 0.80rem);
  --text-sm:   clamp(0.875rem, 0.83rem + 0.22vw, 1rem);
  --text-base: clamp(1rem,     0.95rem + 0.25vw, 1.125rem);
  --text-lg:   clamp(1.125rem, 1rem    + 0.6vw,  1.375rem);
  --text-xl:   clamp(1.25rem,  1rem    + 1.2vw,  1.75rem);
  --text-2xl:  clamp(1.5rem,   1rem    + 2vw,    2.5rem);
  --text-3xl:  clamp(2rem,     1.2rem  + 3vw,    4rem);

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
}

body { font-size: var(--text-base); line-height: 1.65; font-family: system-ui, sans-serif; }
h1   { font-size: var(--text-3xl); line-height: 1.1; margin-bottom: var(--space-6); }
h2   { font-size: var(--text-2xl); line-height: 1.2; margin-bottom: var(--space-4); }
p    { font-size: var(--text-base); margin-bottom: var(--space-4); max-width: 70ch; }

.container {
  width: min(90%, 1200px);
  margin-inline: auto;
  padding-inline: var(--space-4);
}

Common Mistakes

Mistake 1 โ€” Using px for font sizes

โŒ Wrong โ€” ignores user browser font-size preference:

body { font-size: 16px; }
h1   { font-size: 32px; }

โœ… Correct โ€” rem scales with user preferences:

body { font-size: 1rem; }
h1   { font-size: 2rem; }

Mistake 2 โ€” em compounding in nested elements

โŒ Wrong โ€” nested em multiplies unexpectedly:

.parent { font-size: 1.25em; } /* 20px */
.child  { font-size: 1.25em; } /* 25px โ€” compounded! */

โœ… Correct โ€” rem always anchors to root:

.parent { font-size: 1.25rem; } /* 20px */
.child  { font-size: 1.25rem; } /* still 20px */

Mistake 3 โ€” Using vw for font sizes without a minimum

โŒ Wrong โ€” unreadably tiny on small screens:

h1 { font-size: 5vw; }

โœ… Correct โ€” clamp() provides floor and ceiling:

h1 { font-size: clamp(1.5rem, 5vw, 4rem); }

▶ Try It Yourself

Quick Reference

Unit / Function Type Resolves Against
px Absolute CSS device pixel
rem Relative Root html font-size
em Relative Current element’s font-size
% Relative Parent’s same dimension
vw Viewport 1% viewport width
vh Viewport 1% viewport height
ch Relative Width of “0” glyph
clamp(a,b,c) Function min a, preferred b, max c

🧠 Test Yourself

A user sets browser font to 20px. Your CSS has font-size: 1.5rem. What is computed?





โ–ถ Try It Yourself