Free · Fast · Privacy-first

CSS Dark Mode Background Generator

CSS dark mode backgrounds switch automatically with the user system preference when built with CSS custom properties and the prefers-color-scheme media query, and they can also respond to a manual toggle button if you add a small JavaScript helper.

Generates CSS custom property declarations for light and dark backgrounds

🔒

Includes prefers-color-scheme media query for system-level dark mode

Preview light and dark backgrounds side by side in the tool

Supports class-based dark mode toggling for manual override

Cost
Free forever
Sign-up
Not required
Processing
In your browser
Privacy
Files stay local
FreeNo signupWhite-label

Add this Background Gen to your website

Drop the Background Gen into any page — blog post, product docs, intranet, school portal — with a single line of HTML. Your visitors get the full tool, processed entirely in their browser. No backend, no uploads, no signup.

  • Files stay 100% in the visitor's browser
  • Responsive — adapts to any container width
  • Free forever, no API key needed

Embed code

<iframe
  src="https://www.fixtools.io/css-tool/background-gen?embed=1"
  width="100%"
  height="780"
  frameborder="0"
  style="border:0;border-radius:16px;max-width:900px;"
  title="Background Gen by FixTools"
  loading="lazy"
  allow="clipboard-write"
></iframe>

Attribution-friendly: a small "Powered by FixTools" link appears in the embed footer.

CSS Variables, prefers-color-scheme, and Dark Mode Background Systems

A CSS custom property dark mode system defines background colours as variables on :root and overrides them inside the prefers-color-scheme: dark media query. A minimal setup: :root { --bg-page: #ffffff; --bg-card: #f8fafc; } @media (prefers-color-scheme: dark) { :root { --bg-page: #0f172a; --bg-card: #1e293b; } }. Every element using background: var(--bg-page) automatically switches colour based on the system preference. Adding a new themed element requires only using the existing variable, not creating a new media query rule. This scales to dozens of background colours without duplication.

Class-based dark mode toggling provides user control independent of system settings. Define the dark background overrides under a .dark class on the html or body element: html.dark { --bg-page: #0f172a; } JavaScript toggles the class based on a user preference stored in localStorage. This approach works alongside prefers-color-scheme: use the media query as the default and let JavaScript override it when the user explicitly chooses. A common implementation checks localStorage first, falls back to prefers-color-scheme, and applies the result before the first paint to avoid a flash of the wrong theme.

Background colour selection for dark mode is not simply inverting the light mode palette. Light mode backgrounds are near-white (95-99% lightness in HSL). Dark mode backgrounds work best in the 5-20% lightness range. Surface elevation in dark mode should use progressively lighter backgrounds: #0f172a for the page background, #1e293b for cards, and #334155 for elevated surfaces. Using very dark backgrounds like #000000 creates harsh contrast at the edges of components and makes shadows invisible. The Material Design and Tailwind dark mode palettes both use slate-series greys rather than pure black for this reason.

Text and accent colour contrast must be recalculated for dark backgrounds, not simply darkened or lightened mechanically. The WCAG 2.1 contrast ratio of 4.5:1 for body text and 3:1 for large text applies in both modes, but the colours that hit those ratios in light mode often fail in dark mode and vice versa. Body text on a #0f172a page background should typically land near #e2e8f0 (close to 13:1 contrast) for comfortable reading, while muted text should sit near #94a3b8 (about 5.5:1) to remain accessible without competing for attention. Accent colours often need to shift toward higher lightness in dark mode: a brand blue that reads well at #2563eb on white may need to lighten to #60a5fa on a dark background to maintain visual identity and pass contrast checks at the same time.

How to use this tool

💡

Enter light mode and dark mode background colours for each surface level (page background, card background, surface). The tool generates the :root CSS variable declarations, the @media (prefers-color-scheme: dark) overrides, and an optional .dark class toggle pattern for JavaScript-controlled dark mode switching.

How It Works

Step-by-step guide to css dark mode background generator:

  1. 1

    Enter light and dark background colours

    Input background colours for page, card, and surface levels for both light and dark modes. The tool accepts hex, rgb, and hsl values. For a coherent palette, start from a single hue and adjust only lightness across the surface scale rather than picking different colours per level, which usually looks accidental.

  2. 2

    Choose implementation approach

    Select prefers-color-scheme only for a system-driven theme, class-based toggle only for a manual user setting that ignores the OS preference, or both layered so the system preference is the default and the manual toggle overrides it. Both layered is the most accommodating choice for real users.

  3. 3

    Preview both modes

    Toggle the preview between light and dark to check contrast and surface depth at each elevation level. Look at the borders between adjacent surfaces; if you cannot distinguish a card from the page background at one mode, widen the lightness gap between those two variables before exporting.

  4. 4

    Copy the CSS variable block

    Copy the :root variable declarations, media query overrides, and the optional .dark class selector. Paste into your global stylesheet at the top of the CSS so the variables are defined before any rule that consumes them, and add the inline anti-flash script to your HTML head if you enabled the class-based toggle.

Real-world examples

Common situations where this approach makes a real difference:

Developer adding dark mode to an existing site

A developer is retrofitting dark mode to a site with hardcoded background colours throughout the CSS. They use the tool to generate a CSS variable system with five background levels matching the existing light mode colours. They replace every hardcoded background-color with the corresponding var() call, then add the dark mode media query block. The refactor takes one afternoon and adds full system-aware dark mode support without JavaScript.

Designer building a new dark-first design system

A designer starts a new project with dark mode as the default and adds a light mode toggle. They define dark backgrounds at five elevation levels from #0a0f1e to #2d3748, then derive light equivalents by inverting the lightness values. The tool generates both :root and html.light class declarations. The dark backgrounds are the :root default, and light overrides use the .light class toggled by JavaScript.

Frontend engineer preventing white flash on dark mode page load

A user reports seeing a white flash on every page load when their system is in dark mode. The engineer identifies that the dark class is applied by a deferred JavaScript file that runs after first paint. They move the theme detection to an inline script in the HTML head that reads localStorage synchronously and applies the class before the page renders. The tool provides the minimal inline script pattern alongside the CSS variable declarations.

Accessibility specialist verifying dark mode contrast

An accessibility specialist checks every text-on-background combination in the dark mode palette using the background colour generator contrast checker. They find that muted text at #64748b on the darkest background (#0f172a) falls below AA at 3.2:1. They adjust the muted text colour to #94a3b8, which passes AA at 5.1:1. All verified passing combinations are documented in the design system colour token specification.

Pro tips

Get better results with these expert suggestions:

1

Define a full surface scale, not just two colours

Define --bg-base, --bg-surface, --bg-elevated, and --bg-overlay as four separate levels. In dark mode, each should be approximately 5-8 lightness points apart. This creates visible depth between components at all levels without resorting to box shadows, which are often invisible on dark backgrounds.

2

Use color-scheme: light dark on :root

Adding color-scheme: light dark to :root tells the browser to apply system-appropriate scrollbar, form control, and selection colours for both modes automatically. This handles many native UI elements without explicit CSS overrides.

3

Shadow intensity needs adjustment in dark mode

Box shadows using rgba(0,0,0,0.2) are invisible on dark backgrounds because the shadow colour blends into the dark surface. Increase shadow opacity to rgba(0,0,0,0.5) or switch to rgba(0,0,0,0.8) in dark mode, or use coloured shadows that contrast with the dark surface.

4

Set transition on background-color for smooth theme switching

Add transition: background-color 0.2s ease, color 0.2s ease to the body or :root. When the dark class is toggled, the background and text colours animate between values rather than switching instantly. Wrap this in @media (prefers-reduced-motion: no-preference) so users who prefer reduced motion get an instant switch.

5

Use HSL variables for easy dark mode colour derivation

Define --hue and --saturation separately from lightness. In dark mode, change only --bg-lightness from 97% to 8% per surface level. All surfaces share the same hue and saturation, keeping the palette harmonious across both modes.

6

Avoid the flash of incorrect theme

Apply the theme class to the html element in an inline script block in the head before the body renders. Reading localStorage and applying .dark synchronously prevents the white flash on page load for users in dark mode.

7

Test dark mode at real device brightness

Dark backgrounds look different at 50% screen brightness than at 100%. Test dark mode backgrounds on a physical device at typical ambient brightness settings to confirm the surface elevation differences remain visible.

FAQ

Frequently asked questions

Define background colours as CSS custom properties on :root for light mode, then override them inside @media (prefers-color-scheme: dark) { :root { } }. Every element using var(--bg-*) automatically switches based on the user system preference. This approach requires no JavaScript and switches colour based on the operating system dark mode setting in macOS, Windows, iOS, and Android.
prefers-color-scheme is a CSS media feature that detects the user OS colour preference. @media (prefers-color-scheme: dark) matches when the user has set dark mode in their operating system settings. @media (prefers-color-scheme: light) matches the light preference. No-preference was a third value in early drafts but has been removed from the specification. All modern browsers and operating systems support prefers-color-scheme. In an unsupported browser, the media query does not match and the light (default) styles apply.
Use both. prefers-color-scheme handles the automatic system-preference case. A .dark class on the html element enables a JavaScript-controlled override for a user preference toggle button. Store the override in localStorage and apply the class in an inline script before the body renders to prevent a flash of the wrong theme. This pattern covers all cases: users without a system preference, users who want to override their system setting, and users who rely on automatic switching.
Avoid pure black. Use dark navy or dark slate colours for page backgrounds: #0f172a or #0a0f1e. Cards and surfaces should be progressively lighter: #1e293b for cards, #334155 for elevated surfaces. Each level should differ by approximately 6-10 lightness points in HSL to create visible depth. Very dark surfaces like #0a0a0a look harsh and make component borders invisible. Base your scale on an established palette like Tailwind Slate or Material Design dark surfaces.
Apply the dark theme class to the html element in an inline script block in the HTML head, before any stylesheet or body content loads. The script reads localStorage for a stored preference, falls back to matchMedia prefers-color-scheme, and applies the class synchronously. Because it runs before the first paint, the correct background is applied before any content renders. Deferred scripts and DOMContentLoaded handlers run too late and cause the flash.
Use CSS custom properties for background-image values as well as colours. Define --bg-texture: url(light-texture.png) in light mode and override to url(dark-texture.png) in the dark mode media query or .dark class. For gradient backgrounds, define the gradient as a custom property string. This keeps all background changes in one place in the CSS rather than scattered across multiple selectors.
No. prefers-color-scheme only switches styles within the media query blocks you define. Gradients are not automatically inverted. You must define separate gradient values for dark mode and apply them via CSS custom property overrides inside the prefers-color-scheme media query. Hardcoded gradient values remain unchanged regardless of dark mode. This is why using CSS variables for all theme-dependent colours is important: it makes dark mode overrides maintainable.
Add transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease to the body and major layout elements. When the .dark class is toggled by JavaScript, these elements animate between light and dark values. Wrap the transition declaration in @media (prefers-reduced-motion: no-preference) so users with a reduce-motion preference get an instant switch rather than an animation. Do not use prefers-color-scheme for the automatic system preference switch because users who change system settings at the OS level expect an immediate change rather than a fade between states.
Implement a class-based toggle on the html element using a small JavaScript helper. The button reads the current state, flips a value in localStorage between "light" and "dark", and adds or removes a .dark class on document.documentElement. Your CSS then needs three layers: :root defaults (light), @media (prefers-color-scheme: dark) :root for automatic dark, and html.dark or html.light selectors to force the choice when the user has explicitly toggled. To prevent a flash on page load, run the script inline in the HTML head before any stylesheet so the class is applied before first paint.
Yes, for two reasons. First, system-wide dark mode usage has grown steadily on phones and is over 50 percent in some regions for evening browsing, so even when daytime traffic skews light the same users may visit at night and prefer dark. Second, accessibility regulations and corporate procurement increasingly treat dark mode as a baseline accommodation for users with light sensitivity, certain visual impairments, or photophobia. A site that supports prefers-color-scheme automatically is a measurably better experience for those users, costs almost nothing to add when designed in from the start, and avoids retrofit work later when a customer or auditor asks for it.

Ready to get started?

Open the full Background Gen — free, no account needed, works on any device.

Open Background Gen →

Free · No account needed · Works on any device