figma guide
Dark Mode Design in Figma: Tokens & Preview Tricks
Ship dark mode in Figma without guesswork: semantic color tokens, mode switching, contrast checks, preview tricks, and a migration checklist designers can run today.
- Published
- Updated
- May 23, 2026
- Read time
- 7 min
- Level
- Intermediate
Quick answer
Dark mode in Figma is not a separate file trick—it is a mode on your color variables (and sometimes spacing or elevation tokens) that swaps semantic values while components stay bound to roles like surface/default and text/primary. Author semantic tokens first, add Light and Dark modes on that collection, preview with the file mode switcher and prototype flows, then audit contrast before handoff. If you only tint a few frames manually, you will ship inconsistent grays and broken components; if you bind at the system layer, one switch updates screens consistently.
Start from the Figma guides hub for setup context. For the underlying mechanics, read Variables & modes in Figma: a designer-first explainer before you scale dark palettes across libraries.
Dark mode is a system problem, not a recolor pass
Teams that “paint everything dark” in one sprint usually create three long-term debts: orphan hex on detached layers, components that look correct in light but leak bright fills in dark, and marketing frames that never sync when product tokens change. Dark mode succeeds when the same component instances work in both modes because bindings point at variables with mode-specific values.
| Approach | Speed | Maintainability | When it fits |
|---|---|---|---|
| Manual frame fills | Fast for one mock | Poor | One-off pitch decks |
| Duplicate light/dark components | Medium | Fragile | Legacy files before Variables |
| Variables + modes | Slower upfront | Strong | Product UI, design systems |
| Variables + styles hybrid | Medium | Good | Teams that keep text styles for picker UX |
Verdict: for product work, invest in semantic variables and modes. Keep styles where they improve designer speed, but stop hardcoding #FFFFFF on surfaces you expect to theme.
Token architecture for light and dark
Foundations vs semantics
Split tokens into two layers:
- Foundations — raw ramps (
neutral/50…neutral/950, brand hues). These rarely appear on components directly. - Semantics — roles the UI understands (
bg/default,bg/elevated,text/primary,border/subtle,focus/ring).
Dark mode changes semantic values, not component structure. A button still binds to bg/brand and text/on-brand; only the resolved hex shifts per mode.
Use aliases so semantics stay stable when brand ramps change. That pattern is covered in depth in Variables & modes; the dark-mode-specific discipline is ensuring every semantic has a dark value before you publish the library.
What usually needs a dark counterpart
| Token role | Light typical behavior | Dark typical behavior |
|---|---|---|
surface/default | Near-white canvas | Deep neutral, not pure black |
surface/elevated | Subtle shadow cards | Slightly lighter gray layer |
text/primary | Near-black | Off-white, not #FFFFFF everywhere |
text/secondary | Mid gray | Muted gray with enough contrast |
border/default | Light hairlines | Low-contrast separators |
brand/primary | Saturated accent | Often slightly desaturated for glare |
focus/ring | High visibility | Same intent, recheck contrast |
Common mistake: using pure black (#000000) for app backgrounds. It crushes elevation, makes shadows meaningless, and tires eyes on OLED. Most systems use dark gray surfaces (#121212–#1A1A1A range) with stepped elevation.
Authoring modes in Figma (workflow)
- Audit top screens in light mode: list the 15–25 fills that appear on buttons, inputs, nav, tables, and modals.
- Map each to a semantic name; avoid naming by hex in the variable panel.
- Create or extend a semantic color collection with modes Light and Dark.
- Enter dark values pairwise—for each semantic, set light and dark before moving to the next screen.
- Rebind components at the root; fix stragglers with a quick pass through instances.
- Preview with the variable mode control on key templates: dashboard, settings, empty state, marketing hero (if shared library).
When engineering expects JSON tokens, pair this workflow with your handoff stack—best Figma dev handoff plugins compares tools that sync names and values. Install community plugins safely via how to install a Figma plugin.
Preview tricks designers actually use
File-level mode switching
Switching the active mode for variables updates bound layers on the canvas without duplicating frames. Use this when reviewing component sets and library files before publish.
Side-by-side comparison frames
Create a cover page with two frames: same component instances, different mode applied (or duplicate the page and switch mode per page). Stakeholders compare faster than toggling one frame repeatedly.
Prototype preview
For flows that must feel correct in dark mode during reviews, build prototypes from components already bound to variables, then switch mode before presenting. If you are new to flows, how to use Figma to create a prototype covers state basics—dark mode is not a separate prototype feature, it follows your component bindings.
Presentation and slides
Marketing slides inside Figma benefit from the same tokens when product and brand share a library. For deck layout patterns, see slide decks in Figma: layout, grids, and presenting modes.
Browser vs desktop
Dark previews in the browser app can differ slightly in performance from desktop. If reviewers complain about lag on large libraries, read working with Figma in browser: limitations and performance.
Contrast, accessibility, and “almost dark” UI
Dark mode fails accessibility when secondary text or disabled states are treated as afterthoughts. Plan contrast for:
- Body text on default surfaces
- Placeholder and hint text on inputs
- Icons on tinted brand buttons
- Focus rings on both light and dark
Plugin-assisted checks help during audits; compare options in best Figma plugins for accessibility (2026). Native discipline still matters: do not rely on opacity alone to fix contrast—prefer dedicated semantic tokens for disabled and muted roles.
Practical rule: if you lower opacity on light mode text for “muted,” define an explicit text/tertiary token in dark mode instead of copying the same opacity value.
Elevation, borders, and shadows in dark UI
Light interfaces lean on shadows; dark interfaces often lean on lighter surface steps and subtle borders.
| Technique | Light UI | Dark UI |
|---|---|---|
| Card separation | Shadow + white card | surface/elevated step |
| Hairline dividers | border/subtle | Slightly brighter border token |
| Modals | Shadow stack | Elevated surface + scrim token |
| Brand panels | Tinted wash | Desaturated wash, watch contrast |
Bind scrim colors for overlays (scrim/default at 40–60% opacity) as variables so modals and drawers stay consistent.
Components: interactive states in dark mode
Buttons, inputs, and toggles need hover, pressed, and disabled semantics in both modes. If you use interactive components, extend the same variable bindings rather than one-off overrides per state.
Interactive components: hover, press, disabled states walks through state patterns that pair well with token-driven fills.
Common mistake: only styling default and hover in dark mode, leaving disabled as light-gray on dark gray (illegible). Add surface/disabled and text/disabled tokens early.
Migration checklist (light-only file → dual mode)
- Freeze new hardcoded fills for one release cycle.
- Export a screenshot inventory of top 10 screens for stakeholder sign-off.
- Create semantic variables for surfaces, text, borders, brand, focus.
- Add Dark mode; fill every semantic—no empty cells.
- Rebind buttons, inputs, nav, tables first; illustrations last.
- Run a contrast pass and fix tertiary text.
- Publish library with release notes naming breaking variable changes.
- Schedule quarterly review when Figma ships UI updates—Figma quarterly check-in helps track platform changes.
For library hygiene before migration, how to organize a Figma file so it scales reduces noise that hides unbound fills.
Collaboration with engineering
- Name tokens for role, not appearance (
text/primary, notwhite-90). - Document which modes exist and what triggers mode in production (system setting, user toggle, time-based).
- Align token JSON naming with Figma variable paths where possible.
- When code supports prefers-color-scheme, design both modes even if v1 ships light-only—prevents rework.
Design-system maintainers should cross-link best Figma plugins for design systems for linting and token export tooling.
FAQ
Do I need separate Figma files for dark mode?
Usually no. One library with modes is easier to maintain. Separate files make sense only when dark is a fundamentally different product skin with divergent components.
Can I use color styles instead of variables?
Styles work for single-theme files. The moment you need one binding, two themes, variables and modes are the native answer.
Why does my dark mode look “muddy”?
Often too many similar grays without elevation steps, or shadows copied from light mode. Introduce clearer surface/elevated steps and reduce heavy shadows.
How do I preview dark mode in prototypes shared with stakeholders?
Share a link after switching the file’s variable mode to Dark, or duplicate the prototype flow on a dark-configured page. Confirm viewers know mode is design-controlled, not a live OS toggle unless you prototype that behavior separately.
Should icons change in dark mode?
Stroke and fill icons should use semantic icon tokens (icon/primary) like text. Multi-color marketing icons may stay unchanged—document exceptions.
Bottom line
Dark mode in Figma succeeds when semantic color variables drive components, Light and Dark modes hold paired values, and you preview with the same discipline you use for light QA—contrast, elevation, and interactive states included. Start with surfaces and text, bind components once, then expand to marketing and illustrations. Treat dark mode as a library capability, not a one-time recolor sprint.
§ Keep reading