CSS light-dark() Generator: Automatic Dark Mode Colors Without Media Queries
Learn how the CSS light-dark() function simplifies dark mode theming, and build copy-ready color pairs with the free CSS Light-Dark() Generator.
Table of Contents
Dark mode used to mean doubling your color declarations: one value for light theme, a second inside a prefers-color-scheme media query, and a third inside your .dark class override for manual toggles. Multiply that across every color in your design system and your stylesheet becomes a maze of near-duplicate rules. The CSS light-dark() function makes that entire pattern obsolete with a single line.
With light-dark(), you declare both theme colors in one place, and the browser picks the right one automatically based on the active color scheme. Our CSS Light-Dark() Generator gives you color pickers for both values, a live side-by-side preview, and three copy-ready outputs β the raw value, a complete rule, and a full snippet with color-scheme included.
In this guide, you'll learn how the function works under the hood, how it differs from media-query-based theming, and how to use the generator to build adaptive color pairs in seconds.
Why Use the CSS Light-Dark() Generator?
- One declaration, two themes. light-dark() collapses paired light/dark colors into a single value, cutting the repetitive blocks that media-query theming demands.
- Live preview as you tweak. The generator renders Light βοΈ and Dark π preview cards in real time, so you see exactly how both values behave before committing them to your stylesheet.
- Ten properties supported out of the box. Pick from color, background-color, border-color, text-decoration-color, fill, stroke, outline-color, caret-color, box-shadow color, or enter any custom property like --my-brand-color.
- Three output formats. Copy just the light-dark() value for inline use, a single complete CSS rule, or a full snippet that includes the color-scheme: light dark; declaration the function depends on.
- No media queries required. Because the browser resolves the pair natively, you stop maintaining @media (prefers-color-scheme: dark) blocks for every single color.
- 100% client-side and free. Everything runs in your browser β no signup, no uploads, no server round-trips. Your color choices never leave your machine.
Key Features
| Feature | What it does |
|---|---|
| Light & dark color pickers | Choose hex values for each theme, with text inputs for precision (defaults #ffffff / #1a1a1a) |
| Property selector | Target any of nine common CSS properties or a custom property of your choice |
| Live preview cards | Side-by-side Light and Dark renders with color-scheme applied, showing both hex codes |
| Copy-ready outputs | Three separate copy buttons for value, rule, and full snippet |
| color-scheme included | The full snippet ships with the color-scheme: light dark; line so the pair activates correctly |
The property selector deserves a mention: because light-dark() is a color value (not a property), it works anywhere a color is accepted β including SVG fill and stroke, caret-color, and custom properties. The generator's dropdown generates the correct rule shape for each target so you never hand-assemble it.
The full-snippet output is the safest starting point for real projects. It pairs your value with color-scheme: light dark;, which is the switch the browser uses to decide which side of the pair to render. Copying the value alone works, but only if color-scheme is already set somewhere in scope.
How to Use
- Open the CSS Light-Dark() Generator β no account needed.
- Pick your light mode color and dark mode color using the two color pickers, or type exact hex values like #1a1a1a.
- Choose the CSS property you're theming from the dropdown β or select custom property and type a name like --brand-accent.
- Watch the live preview update: the Light card shows your first color, the Dark card shows the second, each under its own color-scheme.
- Click Copy on the output you need β the light-dark() value, the single rule, or the full snippet with color-scheme: light dark; β and paste it into your stylesheet.
Understanding light-dark() and color-scheme
The light-dark() function takes exactly two arguments β a color for light scheme and a color for dark scheme:
.button-text {
color: light-dark(#1a1a1a, #ffffff);
}
When the page is rendered in a light color scheme, the browser resolves the value to #1a1a1a. In a dark color scheme, it resolves to #ffffff. There's no cascade trickery and no duplicated selectors β the resolution happens at the value level.
The function only works when the element is inside a context that opts into both schemes:
:root {
color-scheme: light dark;
}
This declaration tells the browser "this document supports both light and dark," and it becomes the switch that flips every light-dark() value on the page. If you want a manual theme toggle instead of following the OS setting, set color-scheme: light; or color-scheme: dark; on the root at runtime β every light-dark() pair follows instantly, which is dramatically simpler than toggling a class and re-declaring colors.
Browser support is solid on modern engines: Chrome and Edge 123+, Firefox 120+, and Safari 17.5+. For older browsers, provide a fallback with @supports:
:root {
color-scheme: light dark;
}
.text-primary {
color: #1a1a1a; /* fallback for older browsers */
}
@supports (color: light-dark(#fff, #000)) {
.text-primary {
color: light-dark(#1a1a1a, #ffffff);
}
}
How is this different from @media (prefers-color-scheme: dark)? The media query approach duplicates every rule that changes color: once for the default, once inside the query. light-dark() inverts that β the pair lives in one declaration, and color-scheme (which can be driven by a media query, a class, or JavaScript) flips everything at once. You get the same automatic OS-following behavior with far less CSS, plus manual toggling becomes a one-property change.
Practical Use Cases
Theming a design system
Design tokens are pairs by nature β every "surface," "text," and "border" token has a light and dark variant. Express them directly:
:root {
color-scheme: light dark;
--color-text: light-dark(#1a1a1a, #f5f5f5);
--color-surface: light-dark(#ffffff, #171a26);
--color-border: light-dark(#e5e5e5, #2e3450);
}
Every component that consumes these tokens becomes theme-aware with zero extra rules.
Brand color pairs
Brand colors rarely map one-to-one between themes β a saturated blue might need a lighter, desaturated variant on dark backgrounds for comfortable contrast. The generator's side-by-side preview is built for exactly this: dial in the dark variant until both cards feel balanced, then copy the pair.
Migrating legacy dark-mode CSS
If your stylesheet is full of @media (prefers-color-scheme: dark) overrides, migrate incrementally. Replace one paired property at a time with a light-dark() value, keep the media query until every pair inside it is converted, then delete the empty query. The generator's single-rule output drops straight into this workflow.
Component libraries
Library authors can ship theme-aware components without knowing the host page's theming strategy. A button styled with light-dark() adapts to whatever color-scheme the consuming app sets β no CSS variable contract required, no data-theme attributes to respect.
Best Practices
- Always declare color-scheme: light dark; on :root (or the relevant scope) β without it, light-dark() values won't switch and both themes render the first color.
- Check contrast in both themes. A pair that passes WCAG on light backgrounds can fail on dark ones β run both hex values through a contrast checker before shipping.
- Use the full snippet in new projects so color-scheme and the color pair are always introduced together.
- Wrap in @supports when you must support older browsers, with a plain-color fallback before the enhanced declaration.
- Prefer semantic custom properties. Store pairs in tokens like --color-text and let components reference the token β one place to retheme everything.
- Test the manual toggle path. If you offer a theme switcher, flip color-scheme on the root via JavaScript and confirm every pair responds β it's the fastest way to catch a missing declaration.
Start Generating Adaptive Colors Today
The light-dark() function is the cleanest dark mode primitive CSS has shipped in years β and with the CSS Light-Dark() Generator, turning your color pairs into production-ready CSS takes under a minute. Pick two colors, watch both themes render live, copy the snippet, done.
No more duplicate declarations. No more media-query mazes. Just pairs that adapt on their own. Happy theming!
Related Tools You Might Like:
- Color Scheme Generator β generates full color-scheme declarations
- Color Contrast Checker β verify WCAG contrast in both themes
- CSS color-mix() Generator β blend colors with modern CSS