Complete the lesson quiz and earn 250 XP.
Digital screens are physically flat, two-dimensional surfaces. Yet, users interact with interfaces as though they possess physical depth: dialogs float above pages, dropdowns hover over tables, and buttons depress when clicked.
We create this illusion of three-dimensional depth using Elevation:
Understanding this physical relationship allows design systems to establish realistic, harmonious elevation tokens.
A single, harsh CSS drop shadow like box-shadow: 0 10px 20px rgba(0,0,0,0.4) looks cheap, muddy, and unnatural. In real life, light bounces off nearby walls and surfaces, creating two simultaneous shadows:
Professional design systems combine these into multi-layer shadow tokens:
--elevation-card:
0 1px 3px rgba(0, 0, 0, 0.05), /* Ambient shadow */
0 4px 12px rgba(0, 0, 0, 0.08); /* Directional key shadow */
Multi-layering produces buttery smooth, realistic depth that elevates the entire aesthetic of your product.
To keep interfaces calm and uncluttered, a design system defines five distinct elevation tiers:
#090D16). Table rows, flat list items, and resting containers live here.0 1px 3px ...). Interactive cards, panels, and widgets. Provides subtle separation from the canvas.0 4px 12px ...). Dropdown menus, tooltips, and floating action buttons.0 12px 32px ...). Modal dialogs, side sheets, and full-screen drawers that interrupt user workflows.In light mode, black drop shadows contrast vividly against white canvases. In dark mode, however, a black shadow cast against a dark charcoal background (#0B0F19) is virtually invisible.
The Dark Mode Elevation Formula: Instead of relying solely on shadows, dark interfaces express elevation through luminosity and border highlights:
#0B0F19, Level 1 = #151C2C, Level 2 = #1E293B, Level 3 = #2C3A54).border: 1px solid rgba(255, 255, 255, 0.08)) creates a crisp specular highlight that outlines the elevated boundary.Every web developer has encountered this disaster: an engineer wants a modal to sit on top of a sticky header, so they write z-index: 999. Another engineer wants a toast to sit on top of the modal, so they write z-index: 999999. Soon, the codebase is an unmaintainable war of arbitrary numbers.
A design system ends this chaos with a strict, tokenized Z-Index scale:
z-index-base: 0 (Standard document flow)z-index-dropdown: 100 (Dropdown menus, autocomplete popovers)z-index-sticky: 200 (Sticky navigation bars, fixed headers)z-index-backdrop: 400 (Modal backdrop dimming overlay)z-index-modal: 500 (Modal dialogs, side drawers)z-index-toast: 1000 (Global system notifications, toasts)By banning arbitrary z-index numbers and enforcing tokens via linters, UI elements layer in predictable, perfect order.
Have you ever set z-index: 9999 on a tooltip, but it still rendered underneath a neighboring card? This occurs because of a CSS Stacking Context.
In CSS, z-index values are not global; they only compete against elements within the same stacking context. If a parent container creates a new stacking context, all its children are trapped inside it.
Common CSS properties that unintentionally trigger a new Stacking Context:
transform (e.g., transform: translate(0, 0) or scale(1.02) on card hover)opacity less than 1 (e.g., opacity: 0.99)filter (e.g., backdrop-filter: blur(8px))will-change (e.g., will-change: transform)The Design System Solution: React Portals
Floating elements (tooltips, modals, dropdowns) should render via a Portal directly into document.body at the root level, bypassing all parent stacking contexts entirely.
Elevation is dynamic. When a user hovers over an interactive card or presses a button, the element should feel responsive and alive.
The Physics of Hover Elevation:
--elevation-card, transform: translateY(0)).--elevation-card-hover, transform: translateY(-2px)).transition: all 180ms cubic-bezier(0.16, 1, 0.3, 1)).Notice that moving up 2px (translateY(-2px)) visually reinforces the expanding shadow: the object physically rises off the page toward the user's eye.
Modern operating systems (macOS Tahoe/Sonoma, iOS, Windows Fluent) use frosted glass materials to create subtle depth without completely obscuring background context.
In web design systems, this is achieved using backdrop-filter: blur():
.sticky-header {
background-color: rgba(11, 15, 25, 0.8);
backdrop-filter: blur(12px) saturate(160%);
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
blur(12px) softens underlying text so it doesn't distract; saturate(160%) prevents muddy grayish tones.Consider this real-world bug reported in a production app:
z-index: 500).z-index: 1000) renders on top of the modal's backdrop and cuts off the country dropdown!The Root Cause:
The marketing squad hardcoded z-index: 1000 on their sticky banner, which should have been z-sticky: 200.
The Systemic Fix:
--z-sticky (200).--z-modal (500), naturally covering the sticky banner.--z-dropdown (600 within the modal tier), layering cleanly on top.