Shadows light, outlines dark

Shadows disappear on dark surfaces, so switch to an outline there.

Josh W. Comeau@joshwcomeau.com
The pattern I’ve landed on for this is: - shadows in light mode - outlines in dark mode The “outline” property is great for this because it doesn’t cause layout shifts when it gets added/removed.
Apr 7, 2025View on Bluesky ↗

1 · Does the edge show?

Flip each card between light and dark.

Shadow in both modesBad
Edgebox-shadow
Shadow, then outlineGood
Edgebox-shadow
.card { box-shadow: 0 8px 20px hsl(220 20% 20% / .2); }

@media (prefers-color-scheme: dark) {
  .card {
    box-shadow: none;
    outline: 1px solid hsl(0 0% 100% / .16);
  }
}

2 · Does the page jump?

Switch to dark and watch the lower card.

Border in darkBad
Lower card0px
Outline in darkGood
Lower card0px
/* border adds 2px to the box and pushes its neighbours */
.card { border: 1px solid var(--edge); }

/* outline is painted outside the box and never moves anything */
.card { outline: 1px solid var(--edge); }

Why it matters, pros and cons

Why it matters

A shadow needs light to fall on. On a dark surface it disappears, so an outline draws the edge instead.

Pros

  • Cards keep a visible edge in both themes, with no extra markup.
  • Outline takes no space, so adding or removing it never shifts the layout.
  • Same selectors for hover and focus rings, which already use outline.

Cons

  • Outlines follow the border radius only in newer browsers.
  • Outlines can be clipped by an ancestor with overflow: hidden.
  • You now maintain two edge treatments, one per theme.