Zazz Design Framework
Foundations

Effects

Shadows for elevation, focus rings for accessible orientation.

Two effect groups: shadows for elevation, states for focus.

Effects are the visual signal that something has depth or that a user is interacting with it. Zazz keeps the surface small: six shadow levels and a single focus-ring token. Effects are easy to overspend and hard to recover from. A page covered in shadows reads as cluttered. A page with one focus indicator reads as confident.

Shadows

Six shadow tokens, layered for soft falloff.

--shadow-none: 0px 0px 0px 0px oklch(0% 0 0 / 0);

--shadow-xs:
  0px 0px 0px 0px oklch(0% 0 0 / 0.05), 0px 1px 0px 0px oklch(0% 0 0 / 0.04),
  0px 3px 0px 0px oklch(0% 0 0 / 0.03), 0px 5px 0px 0px oklch(0% 0 0 / 0.01),
  0px 8px 0px 0px oklch(0% 0 0 / 0);

--shadow-sm:
  0px 1px 0px 0px oklch(0% 0 0 / 0.05), 0px 4px 0px 0px oklch(0% 0 0 / 0.04),
  0px 9px 0px 0px oklch(0% 0 0 / 0.03), 0px 16px 0px 0px oklch(0% 0 0 / 0.01),
  0px 25px 0px 0px oklch(0% 0 0 / 0);

--shadow-md:
  0px 3px 0px 0px oklch(0% 0 0 / 0.05), 0px 11px 0px 0px oklch(0% 0 0 / 0.04),
  0px 24px 0px 0px oklch(0% 0 0 / 0.03), 0px 42px 0px 0px oklch(0% 0 0 / 0.01),
  0px 66px 0px 0px oklch(0% 0 0 / 0);

--shadow-lg:
  0px 10px 0px 0px oklch(0% 0 0 / 0.06), 0px 39px 0px 0px oklch(0% 0 0 / 0.05),
  0px 89px 0px 0px oklch(0% 0 0 / 0.03), 0px 158px 0px 0px oklch(0% 0 0 / 0.01),
  0px 247px 0px 0px oklch(0% 0 0 / 0);

--shadow-xl:
  0px 15px 0px 0px oklch(0% 0 0 / 0.07), 0px 59px 0px 0px oklch(0% 0 0 / 0.06),
  0px 133px 0px 0px oklch(0% 0 0 / 0.04), 0px 237px 0px 0px oklch(0% 0 0 / 0.01),
  0px 370px 0px 0px oklch(0% 0 0 / 0);

Each shadow stacks multiple entries with decreasing opacity and increasing vertical offset. A single shadow with a large blur reads as a halo around an object. A stack of progressively softer shadows reads as natural elevation. The opacity values run small (0.01 to 0.07 per layer) so the cumulative effect stays subtle.

.card {
  box-shadow: var(--shadow-md);
}

.modal {
  box-shadow: var(--shadow-xl);
}

The colors derive from oklch(0% 0 0 / α): pure black at varying opacities. Because the alpha is what's varying, the shadow color picks up the active background through transparency, so the same shadow reads correctly on light and dark surfaces without a second token.

Levels by intent:

  • --shadow-none. Explicit "no shadow," for components that toggle elevation on and off.
  • --shadow-xs. Borders that need a slight lift.
  • --shadow-sm. Resting buttons, hover affordances.
  • --shadow-md. Cards, dropdowns, popovers.
  • --shadow-lg. Modals, side panels.
  • --shadow-xl. The most elevated surface in a view (a single command palette, a centered dialog over a backdrop).

Focus ring

One token covers focus state for every interactive element.

--focus-ring: 0px 0px 0px 4px var(--background), 0px 0px 0px 2px var(--primary);

Two layered shadows. The inner ring is --primary (the active brand color). The outer is --background, a gap that separates the ring from any border the element already has. Because both layers reference theme tokens, the ring adapts to mode automatically: primary lightens in dark mode, background flips to neutral-950.

.interactive:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

Use :focus-visible, not :focus. The ring should appear on keyboard navigation, not on mouse clicks. :focus-visible is the standard mechanism for that distinction.

Where to next

On this page