設計基礎

Elevation

Create depth with light and dark shadow tokens, layered surfaces, and state-aware elevation.

Overview

Elevation describes the relationship between surfaces. In CSS, that relationship is usually rendered with box-shadow, but the design decision is broader than the property: a surface can be grounded on the canvas, raised as a reusable card, detached as an overlay, or placed above the workflow as a modal.

Master CSS maps elevation to the shadow namespace. Use shadow:* tokens for repeated product surfaces instead of copying raw multi-part shadow values into markup. The preset scale is mode-aware, so the same class resolves to a light shadow recipe in light mode and a stronger dark-mode recipe in dark mode.

shadow:xs
Quiet separation

Small controls, table rows, and subtle raised states.

shadow:sm
Standard surface

Cards, reusable panels, and quiet product surfaces.

shadow:md
Temporary lift

Hover lift, floating toolbars, and command surfaces.

shadow:lg
Detached overlay

Dropdowns, popovers, toasts, and menus.

shadow:xl
Workflow interruption

Drawers, dialogs, and focused panels.

shadow:2xl
Blocking layer

Modals and spotlight surfaces above a dimmed page.


Choose an elevation token

Start with the surface relationship, then choose the lowest token that makes that relationship clear. More shadow does not create more hierarchy when every surface competes for depth.

TokenClassRole
--shadow-xsshadow:xsQuiet separation, Small controls, table rows, and subtle raised states.
--shadow-smshadow:smStandard surface, Cards, reusable panels, and quiet product surfaces.
--shadow-mdshadow:mdTemporary lift, Hover lift, floating toolbars, and command surfaces.
--shadow-lgshadow:lgDetached overlay, Dropdowns, popovers, toasts, and menus.
--shadow-xlshadow:xlWorkflow interruption, Drawers, dialogs, and focused panels.
--shadow-2xlshadow:2xlBlocking layer, Modals and spotlight surfaces above a dimmed page.

The role of each token should stay stable across modes. Light and dark recipes can use different opacity, offset, and blur values, but shadow:sm should still mean a standard raised surface in both modes.


Pair elevation with color roles

Elevation needs a visible ground. Pair shadows with surface:*, text:*, and radius tokens so depth reads correctly in light and dark themes.

Raised surface

Cards use a large shadow on a raised surface.

Raised surface

Cards use a large shadow on a raised surface.

<article class="surface:raised r:lg shadow:lg">    <h2 class="text:strong">Raised surface</h2>    <p class="text:muted">Cards need a clear surface before they need a large shadow.</p></article>

Use surface roles for the ground and shadows for separation. A strong shadow on every panel makes the page noisy, even when the surfaces use different color roles.


Use shadow tokens

Use shadow:<token> for common elevation levels. The utility resolves values from shadow-* tokens and emits a stable box-shadow: var(--shadow-*) declaration; the active mode changes the variable value.

<article class="surface:raised r:lg shadow:sm">    ...</article><div class="surface:overlay r:lg shadow:lg">    ...</div>
Generated CSS
@layer theme {    @media (prefers-color-scheme:light) {        :root {            --shadow-sm: 0 0 0 1px oklch(0% 0 none / .04), 0 1px 2px -1px oklch(0% 0 none / .06), 0 3px 6px -2px oklch(0% 0 none / .08);            --shadow-lg: 0 0 0 1px oklch(0% 0 none / .05), 0 4px 8px -4px oklch(0% 0 none / .08), 0 16px 32px -8px oklch(0% 0 none / .12)        }    }    @media (prefers-color-scheme:dark) {        :root {            --shadow-sm: 0 0 0 1px oklch(100% 0 none / .05), 0 1px 2px -1px oklch(0% 0 none / .34), 0 3px 6px -2px oklch(0% 0 none / .26);            --shadow-lg: 0 0 0 1px oklch(100% 0 none / .06), 0 4px 8px -4px oklch(0% 0 none / .42), 0 16px 32px -8px oklch(0% 0 none / .34)        }    }}@layer utilities {    .shadow\:lg {        box-shadow: var(--shadow-lg)    }    .shadow\:sm {        box-shadow: var(--shadow-sm)    }}

Use shadow:* in product markup. Use the explicit box-shadow:* form when documenting native property mapping or when surrounding code benefits from the native property name.


Namespace for elevation

The shadow variable namespace is shared by the elevation shorthand and the native shadow property.

GroupUtility keysDescription
Shadowshadow, box-shadowUse shadow tokens for product elevation and the native property name when surrounding code is clearer that way.

This lets elevation utilities use sm, lg, or project token names without repeating the shadow- prefix.


Change elevation by state

State elevation should communicate interaction, not decoration. A hover shadow can make a card feel liftable; a focus shadow should not replace an accessible focus indicator.

<article class="shadow:sm shadow:md:hover shadow:none@print">    ...</article>
Generated CSS
@layer theme {    @media (prefers-color-scheme:light) {        :root {            --shadow-sm: 0 0 0 1px oklch(0% 0 none / .04), 0 1px 2px -1px oklch(0% 0 none / .06), 0 3px 6px -2px oklch(0% 0 none / .08);            --shadow-md: 0 0 0 1px oklch(0% 0 none / .05), 0 2px 4px -2px oklch(0% 0 none / .06), 0 8px 16px -4px oklch(0% 0 none / .1)        }    }    @media (prefers-color-scheme:dark) {        :root {            --shadow-sm: 0 0 0 1px oklch(100% 0 none / .05), 0 1px 2px -1px oklch(0% 0 none / .34), 0 3px 6px -2px oklch(0% 0 none / .26);            --shadow-md: 0 0 0 1px oklch(100% 0 none / .06), 0 2px 4px -2px oklch(0% 0 none / .38), 0 8px 16px -4px oklch(0% 0 none / .3)        }    }}@layer utilities {    .shadow\:sm {        box-shadow: var(--shadow-sm)    }    .shadow\:md\:hover:hover {        box-shadow: var(--shadow-md)    }    @media print {        .shadow\:none\@print {            box-shadow: none        }    }}

Keep state changes small. Moving from shadow:sm to shadow:md is usually enough for hover. Jumping from shadow:sm to shadow:2xl makes a normal card feel like a modal.


Customize mode-aware shadows

Override the same shadow-* keys in @theme light and @theme dark when your product needs softer depth, sharper enterprise surfaces, or stronger overlays. Keep the token names size-based and mode-neutral so the markup does not fork by theme.

@theme light {    --shadow-sm: 0 0 0 1px oklch(0% 0 none / .05), 0 2px 4px -2px oklch(0% 0 none / .08), 0 8px 20px -6px oklch(0% 0 none / .12);    --shadow-lg: 0 0 0 1px oklch(0% 0 none / .06), 0 10px 20px -8px oklch(0% 0 none / .12), 0 24px 56px -16px oklch(0% 0 none / .16);}@theme dark {    --shadow-sm: 0 0 0 1px oklch(100% 0 none / .05), 0 2px 8px -4px oklch(0% 0 none / .36);    --shadow-lg: 0 0 0 1px oklch(100% 0 none / .07), 0 12px 28px -10px oklch(0% 0 none / .48), 0 28px 64px -18px oklch(0% 0 none / .40);}
<article class="shadow:sm">...</article><div class="shadow:lg">...</div>

Promote repeated raw shadows into the scale. Keep one-off art direction in local markup or component CSS until it proves reusable. If a one-off shadow must differ by mode, prefer promoting it to a token instead of duplicating conditional raw values in markup.


Avoid elevation noise

Every panel competes for depth.

<main class="shadow:lg">    <section class="shadow:xl">        <article class="shadow:2xl">...</article>    </section></main>

Only the surfaces that need separation are elevated.

<main class="bg:surface-base">    <section class="bg:surface-base">        <article class="surface:raised shadow:sm">...</article>    </section></main>

Raw shadows become repeated product decisions without a name.

<article class="shadow:0|4px|12px|black/.12">...</article><aside class="shadow:0|4px|12px|black/.12">...</aside>

Repeated decisions override a shadow scale token.

@theme light {    --shadow-sm: 0 0 0 1px oklch(0% 0 none / .05), 0 4px 8px -2px oklch(0% 0 none / .08), 0 12px 24px -4px oklch(0% 0 none / .10);}@theme dark {    --shadow-sm: 0 0 0 1px oklch(100% 0 none / .06), 0 8px 18px -8px oklch(0% 0 none / .44), 0 18px 40px -12px oklch(0% 0 none / .36);}
<aside class="shadow:sm">...</aside>

  • Master UI


© 2026 Aoyue Design LLC.MIT License
Trademark Policy