Shadows light, outlines dark
Shadows disappear on dark surfaces, so switch to an outline there.
Josh W. Comeau@joshwcomeau.comThe 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.
1 · Does the edge show?
Flip each card between light and dark.
Shadow in both modesBad
Edge
box-shadowShadow, then outlineGood
Edge
box-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 card
0pxOutline in darkGood
Lower card
0px/* 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.