Absolute vs Relative Units in Modern CSS
In CSS layout and web typography, sizing values are split into two major categories: absolute length units (such as `px`, `cm`, `pt`, `in`) and relative length units (such as `rem`, `em`, `%`, `vw`, `vh`, `ch`).
Absolute units are fixed to a physical measurement or hardware reference pixel. In CSS, 1 pixel (`1px`) is formally defined as 1/96th of an inch. While pixels are intuitive and predictable for borders and decorative shadows, relying on fixed pixels for text sizing and container padding causes significant accessibility and responsive layout breakdowns.
Why Hardcoding PX Harms Web Accessibility
Web accessibility guidelines (WCAG 2.2) require that web applications accommodate users with visual impairments who increase their browser’s default font size. By default, major browsers set the root font size to 16 pixels.
However, millions of low-vision users configure their operating system or browser font preference to 20px, 24px, or larger. When a website declares `font-size: 16px` on body elements using hardcoded pixels, it forcefully overrides the user’s deliberate browser preference, rendering text unreadably small for visually impaired visitors.
The Accessibility Imperative
Always use `rem` for typography and spacing. When the user scales their browser font setting, `rem`-based typography scales proportionally and harmoniously.
REM (Root EM): The Standard for Responsive Typography
The `rem` unit stands for "Root EM". It calculates its computed value relative to the font-size of the root HTML element (`<html>`).
Assuming standard browser defaults (where root is 16px):
• 1rem = 16px
• 1.25rem = 20px
• 1.5rem = 24px
• 2rem = 32px
Because all `rem` values across your entire application reference a single global anchor point (the root element), your UI components remain predictable and immune to unintended compounding scaling bugs.
EM: Component-Relative Sizing and Compounding Hazards
Unlike `rem`, which always looks at the root element, `em` is relative to the font-size of the immediate parent element (or the element itself when calculating padding and margins).
This makes `em` ideal for scalable component tokens: if you build a button with `padding: 0.5em 1.0em`, the padding automatically expands or shrinks whenever you modify that specific button’s font-size.
However, using `em` for nested font sizes triggers the notorious "compounding inheritance" trap: if a `<ul>` has `font-size: 0.9em`, three levels of nested lists will shrink successively (0.9 × 0.9 × 0.9 = 0.729em), rendering innermost items microscopic.
Modern Viewport Units: Solving the Mobile Address Bar (dvh/svh)
Historically, CSS `100vh` was intended to represent 100% of the viewport height. However, on mobile browsers (Safari on iOS, Chrome on Android), dynamic browser chrome (the URL address bar and bottom navigation toolbar) slides in and out as the user scrolls.
Using classic `100vh` caused bottom modal buttons to be cut off beneath the mobile address bar. Modern CSS introduced three specialized viewport units to solve this:
• svh (Small Viewport Height): Height when the dynamic address bar is fully expanded.
• lvh (Large Viewport Height): Height when the address bar is retracted/hidden.
• dvh (Dynamic Viewport Height): Automatically adjusts in real-time as the address bar animates on scroll.
Comprehensive CSS Unit Comparison Matrix
Reference table for selecting the optimal unit for each styling requirement:
| Unit | Relative To | Compounding Risk | Best Recommended Use Case |
|---|---|---|---|
| px | Fixed hardware reference pixel | None | 1px hairline borders, box shadows, canvas dimensions |
| rem | Root <html> element font size | None (safe) | All typography, global margins, layout padding, gap |
| em | Immediate parent element font size | High (on font-size) | Component-internal padding, scalable badge icons |
| % | Parent container dimension | Contextual | Fluid column widths, modal dialog max-widths |
| vw / vh | Full viewport width / height | None | Full-screen hero banners, background split layouts |
| dvh | Dynamic mobile viewport height | None | Mobile app shell layouts, full-height slide-over drawers |