CSS Units

What You'll Learn

  • The difference between absolute and relative units
  • How em and rem differ and when to use each
  • Modern viewport units (dvh, svh, lvh) that work on mobile
  • Container query units for truly responsive components
  • The ch unit for optimal reading width
  • Best practices for choosing the right unit for each situation

Introduction to CSS Units

CSS has evolved from basic pixel values to a sophisticated system of units designed for responsive, accessible web design. Modern CSS offers units for every situation—from fixed sizes to fluid layouts that adapt to viewport, container, or font sizes.

Understanding which unit to use is crucial for creating maintainable, accessible websites that work across all devices and respect user preferences.

Absolute Units

Absolute units have fixed sizes that don't change based on other elements. They're measured in real-world or screen units.

Common Absolute Units

  • px - Pixels (most common for screens)
  • cm - Centimeters
  • mm - Millimeters
  • in - Inches
  • pt - Points (1/72 of an inch)
  • pc - Picas (12 points)
.button { border: 1px solid #ccc; /* Pixels for screen */ padding: 10px 20px; } @media print { .content { width: 6in; /* Inches for print */ margin: 1cm; /* Centimeters for print */ } }

Font-Relative Units: em and rem

The most important relative units scale based on font size. Understanding em and rem is essential for accessible, scalable designs.

em - Relative to Parent

The em unit is relative to the font-size of the parent element. It compounds with nesting, which can be both powerful and problematic.

rem - Relative to Root

The rem (root em) unit is relative to the root <html> element's font-size. It doesn't compound, making it more predictable.

html { font-size: 16px; /* Root font size */ } .parent { font-size: 20px; } .em-child { font-size: 1.5em; /* 1.5 × 20px = 30px */ padding: 0.5em; /* 0.5 × 30px = 15px (uses own font-size!) */ } .rem-child { font-size: 1.5rem; /* 1.5 × 16px = 24px (always uses root) */ padding: 0.5rem; /* 0.5 × 16px = 8px */ }

The ch Unit for Reading Width

The ch unit equals the width of the "0" (zero) character in the current font. It's perfect for controlling line length for optimal readability.

Why Line Length Matters

Research shows that lines between 45-75 characters are easiest to read. Too long, and readers lose their place. Too short, and reading becomes choppy.

.content { max-width: 65ch; /* Optimal reading width */ margin: 0 auto; } .sidebar { max-width: 45ch; /* Narrower for sidebar content */ }

Classic Viewport Units

Viewport units let you size elements relative to the browser window. They're essential for full-screen layouts and responsive typography.

The Four Classic Units

  • vw - 1% of viewport width
  • vh - 1% of viewport height
  • vmin - 1% of smaller viewport dimension
  • vmax - 1% of larger viewport dimension
.hero { height: 100vh; /* Full viewport height */ width: 100vw; /* Full viewport width */ } .sidebar { width: 30vw; /* 30% of viewport width */ } .responsive-text { font-size: 4vmin; /* Scales with viewport */ }

Modern Viewport Units (2022+)

New viewport units solve the mobile browser UI problem. They come in three families: Small, Large, and Dynamic.

The Three Families

  • Small (*s) - Assumes browser UI is visible (smaller viewport)
  • Large (*l) - Assumes browser UI is hidden (larger viewport)
  • Dynamic (*d) - Adjusts as browser UI appears/disappears
/* Old way - doesn't work well on mobile */ .hero { height: 100vh; } /* New way - works perfectly! */ .hero { height: 100dvh; /* Dynamically adjusts for mobile UI */ } /* Or be explicit about your needs */ .always-visible { height: 100svh; /* Guaranteed to fit even with UI */ } .max-space { height: 100lvh; /* Use full space when UI hidden */ }

Container Query Units (2023+)

Container query units let you size elements relative to their container, not the viewport. This enables truly modular, reusable components.

How They Work

First, make an element a container with container-type. Then its children can use container query units to size themselves relative to that container.

.card-container { container-type: inline-size; /* Make it a container */ width: 400px; } .card-title { font-size: 5cqi; /* 5% of container width */ } .card-content { padding: 2cqw; /* 2% of container width */ width: 80cqw; /* 80% of container width */ }

Available Units

  • cqw / cqh - Container width/height
  • cqi / cqb - Container inline/block size
  • cqmin / cqmax - Smaller/larger dimension

Percentages

The percentage unit (%) is relative to the parent element's corresponding property. It's the original responsive unit.

Context Matters

What a percentage is relative to depends on the property:

  • width / height - Relative to parent's width/height
  • margin / padding - Always relative to parent's width (yes, even top/bottom!)
  • font-size - Relative to parent's font-size
  • transform - Relative to element's own size
.parent { width: 800px; } .child { width: 50%; /* 400px (50% of parent width) */ padding: 5%; /* 40px (5% of parent WIDTH, not height!) */ font-size: 120%; /* 120% of parent's font-size */ }

Choosing the Right Unit

With so many units available, how do you choose? Here's a decision guide for common situations:

Font Sizes

Use rem - Scales with user preferences, maintains consistency across components.

Spacing (Margins & Padding)

Use rem or em - rem for consistent spacing, em when spacing should scale with local font size (like button padding).

Borders & Shadows

Use px - Keeps lines crisp and consistent across all zoom levels.

Container Widths

Use %, cqw, or ch - % for fluid layouts, cqw for container-based components, ch for readable text widths.

Full-Height Sections

Use dvh - Works correctly on mobile devices with dynamic browser UI.

Responsive Typography

Combine units with clamp() - e.g., clamp(1rem, 2vw, 3rem) for fluid type that scales with viewport but has min/max bounds.

Key Takeaways