How to Design for Dark Mode
Practical dark mode design guide — semantic color tokens, WCAG contrast, Figma Variables for mode switching, and the mistakes to avoid.
Dark mode is one of the most requested features in any product, and one of the most poorly implemented. The problem isn't the colors — it's the thinking behind them.
Why dark mode isn't just inverting colors
Take your light mode design, invert every color, and you'll get something that looks terrible. Saturated colors become neon. Subtle shadows disappear. Text that had good contrast becomes blinding.
Dark mode needs its own intentional color decisions. The relationship between surfaces, text, and interactive elements changes in low-light contexts. You're not reversing — you're redesigning.
Why you need semantic color tokens
If your design uses raw hex values or named palette colors directly (like blue-500 or #3B82F6), dark mode is painful. You have to find and replace every instance.
Semantic tokens solve this. Instead of applying blue-500 to a button fill, you apply color/interactive/primary. That token has a light mode value (blue-500) and a dark mode value (blue-400). Switch the mode, the token updates everywhere automatically.
This is exactly what Figma Variables are designed for. Build your semantic color layer first — before you design a single screen.
A minimal semantic color set to start with:
bg/surface— main page backgroundbg/elevated— cards, modals, overlaysbg/sunken— inputs, code blockstext/primary— body text, headingstext/secondary— captions, labels, placeholderstext/disabled— greyed out textborder/default— dividers, input bordersinteractive/primary— primary button fillinteractive/primary-hover— primary button hoverinteractive/primary-foreground— text on primary button
Contrast requirements (WCAG)
WCAG 2.1 requires:
- AA: 4.5:1 for normal text, 3:1 for large text (18px+ regular or 14px+ bold)
- AAA: 7:1 for normal text, 4.5:1 for large text
Dark mode makes it easy to accidentally fail contrast. Light text on a slightly-too-light dark background is the most common violation. Test every text/background combination in both modes.
Use Stark (the Figma plugin) or WebAIM's contrast checker while you work. Don't leave contrast checking to the end.
Common dark mode mistakes
Pure black (#000000) backgrounds. Real products almost never use pure black. It creates too much contrast with any colored content and looks harsh. Use dark grays: #0F0F0F, #111827, or #1A1A2E depending on your brand. Notion uses #191919. Linear uses #1C1C1E.
Shadows that don't work. Shadows rely on contrast between a layer and the surface behind it. In dark mode, a dark shadow on a dark background disappears. Two approaches: use very subtle shadows with high opacity, or switch to using a lighter border/glow effect instead of a drop shadow.
The same elevation model as light mode. In light mode, you typically make elements feel elevated by lightening them (white cards on a light gray background). In dark mode, elevate elements by making them lighter than the base surface — not by adding shadows. Each level of elevation adds about 5–8% white overlay.
Saturated colors at full strength. hsl(220, 90%, 50%) looks great on white. On a dark background it looks neon and vibrates. In dark mode, reduce saturation slightly and increase lightness. Your blue-500 becomes blue-400 or even blue-300 in dark contexts.
Forgetting images and illustrations. Photos often look fine in both modes. Custom illustrations with white fills look broken in dark mode. Plan for this — either design separate dark mode illustration variants or use illustrations that work on both backgrounds.
Try Figma FreeSetting up Figma Variables for light/dark mode
- Open Local Variables and create a collection called
Colors. - Add two modes:
LightandDark. - Create your primitive palette variables first (these won't have modes — they're just the raw values).
- Create a second collection called
Semantic. Add Light and Dark modes. - For each semantic variable, set the Light value to the appropriate primitive and the Dark value to its dark equivalent.
- Apply only semantic variables to your components.
Now select any top-level frame, and in the right panel you'll see the Variables section where you can toggle between Light and Dark. The entire frame switches instantly.
Testing your design in both modes
Don't design in light mode and then check dark mode at the end. Switch back and forth throughout the process.
Figma's "publish" flow for variables lets your whole team access the same modes, which means developers and designers are always looking at the same color decisions.
Before shipping, check these specifically:
- All text meets WCAG AA contrast in both modes
- Focus states (keyboard navigation rings) are visible in both modes
- Form inputs look distinct from the background in both modes
- Charts and data visualizations remain readable
- Disabled states are clearly different from active states
Dark mode done well isn't harder than light mode — it just requires the right foundation. Build your token system properly and mode switching becomes a single click.
Related
How to Use Variables in Figma
Learn Figma Variables — color, number, string, and boolean types — and set up a real semantic color system with light and dark mode.
How to Create a Design System: A Practical Guide
Step-by-step guide to building a design system from scratch — what to include, what to skip, and which tools to use.
Figma Review 2026: Still the Best UI Design Tool?
An honest Figma review covering features, pricing, performance, and whether it's worth the subscription in 2026.