Quick implementation
/* HTML: <div class="card">Content</div> */
/* Basic tinted shadow */
.card--basic {
box-shadow: 0 4px 16px oklch(0.15 0.03 260 / 0.4);
}
/* Hue-matched tinted shadow */
.card--tinted {
box-shadow: 0 4px 20px oklch(0.12 0.03 260 / 0.6);
}
/* Full layered shadow stack */
.card--layered {
box-shadow:
0 2px 6px oklch(0.08 0.02 260 / 0.5),
0 8px 24px oklch(0.10 0.03 260 / 0.4),
0 0 0 1px oklch(0.30 0.03 260 / 0.4),
inset 0 1px 0 oklch(1 0 0 / 0.04);
}
Prompt this to your LLM
Includes role, constraints, two framework variants, and edge cases to handle.
You are a senior frontend engineer building a dark-mode design system.
Goal: Create box-shadow utilities that produce visible depth on dark backgrounds using tinted oklch() shadows.
Technical constraints:
- All shadows must use oklch() with low lightness (0.08–0.15) and same hue as the dark background.
- Opacity must be 0.4–0.7 for visibility on dark surfaces.
- Layered shadows separate into: directional (tight), ambient (diffuse), border ring (0 spread), and inner highlight (inset).
- Use var(--accent) for accent glow variants.
- Include prefers-reduced-motion support for any shadow transitions.
Framework variant (pick one):
A) Vanilla CSS utility classes — .shadow-sm, .shadow-md, .shadow-lg, .shadow-glow.
B) React component — accept asChild prop, variant prop (basic|tinted|layered|glow), and className.
Edge cases to handle:
- Cards over images: use ring-only shadow (0 0 0 1px) to avoid competing with image detail.
- Hover state: animate box-shadow 0.25s ease for interactive elements.
- Accent glow: use var(--accent) in oklch() for status indicators (error=red, success=green).
- Overflow: document that shadow wrappers need overflow: visible.
Return CSS only.
Why this matters in 2026
Dark mode shadows are the #1 mistake teams make when porting light mode designs — semi-transparent black shadows that disappear entirely against dark backgrounds because dark plus dark equals no visible contrast. Physical shadows create depth by being darker than the surface; on dark backgrounds, you need tinted shadows with higher opacity to create the illusion that a card is floating above the surface. The oklch() color model makes this intuitive: low lightness values (0.08–0.15) with the same hue as your background create realistic depth that feels intentional rather than arbitrary.
The logic
The tinted shadow technique uses oklch() with low lightness (0.08–0.15) and the same hue as the dark background, then raises alpha to 0.4–0.7 for visibility. Layering multiple shadow values in one declaration simulates realistic depth: a tight directional shadow (0 2px 6px) for the drop, a diffuse ambient shadow (0 8px 24px) for soft edges, a zero-spread ring (0 0 0 1px) for a crisp border effect, and an inset 0 1px 0 inner highlight to simulate light catching the top edge.
Accessibility & performance
Shadows are purely decorative and carry no semantic meaning, so there are no ARIA requirements. They don't affect document flow or keyboard navigation. As a paint property, box-shadow doesn't trigger layout recalculation — animating shadows repaints but stays GPU-accelerated in modern browsers. For interactive hover states, add will-change: box-shadow to promote the element to its own compositor layer. Users with prefers-reduced-motion should still see static shadows; only transitions should be suppressed.