October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
CSS

HTML Dark Mode Switch: Follow System Settings or Add a Saved Toggle

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use CSS prefers-color-scheme for a dark-mode design that follows the visitor’s system setting, then add a small JavaScript toggle only if visitors should be able to choose and save a site-specific preference. Declare supported schemes with color-scheme and a color-scheme meta tag so browser controls can adapt too. The CSS baseline still works if JavaScript is unavailable; a saved override needs early initialization to reduce a first-paint flash.

Choose between system-following dark mode and a manual switch

A dark-mode switch is not required for a page to support dark mode. The simplest approach follows the light or dark preference expressed by the operating system or user agent. CSS handles that without JavaScript. Add a manual control when visitors need to override the system preference for your site; persist their explicit choice and let it take precedence until they return to system default.

Approach User control System changes Persistence JavaScript Initial mismatch risk
System-following CSS only Uses the visitor’s system or user-agent preference CSS media query follows the preference Uses the system setting; no site-specific saved choice Not needed No JavaScript-induced mismatch; page colors follow CSS
System default plus manual override Visitor can choose light, dark, or system System changes apply while system is selected; a pinned choice stays in effect Explicit choice can be saved in localStorage Needed for control and persistence Possible if saved choice is applied after first paint

For a new page, begin with the CSS baseline even if you expect to add a switch later. Google Chrome’s Modern Web Guidance recommends CSS that defaults to the system preference, with overrides for user-specified schemes. Read the current dark-mode guidance.

Build the system-aware CSS baseline

Define paired foreground and background colors, plus surface, border, and accent tokens. The dark palette is not simply an automatic inversion: you choose the colors and must check that each combination remains legible. The prefers-color-scheme media feature reflects a light or dark preference expressed through operating-system or user-agent settings. MDN documents the media feature.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents

Put the color-scheme meta element near the beginning of the document head, before CSS information. Declaring light dark tells the browser both schemes are supported. In a list of schemes, the first is preferred and the next is acceptable; only dark is invalid. See MDN’s meta element reference.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="color-scheme" content="light dark">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>System-aware theme</title>
  <style>
    :root {
      color-scheme: light dark;
      --page: #ffffff;
      --surface: #f2f4f7;
      --text: #1b1d21;
      --muted: #555d69;
      --border: #c8ced8;
      --accent: #174ea6;
    }

    @media (prefers-color-scheme: dark) {
      :root {
        --page: #15171a;
        --surface: #22262b;
        --text: #f1f3f5;
        --muted: #c1c7d0;
        --border: #515965;
        --accent: #a9c7ff;
      }
    }

    body {
      margin: 0;
      padding: 2rem;
      background: var(--page);
      color: var(--text);
      font: 1rem/1.6 system-ui, sans-serif;
    }

    .card {
      max-width: 42rem;
      padding: 1.5rem;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: .75rem;
    }

    a { color: var(--accent); }
    .muted { color: var(--muted); }
  </style>
</head>
<body>
  <main class="card">
    <h1>System-aware theme</h1>
    <p>This page follows the system color preference.</p>
    <p class="muted">Check the text, links, borders, and surfaces in both modes.</p>
  </main>
</body>
</html>

color-scheme informs the browser about the schemes supported by the document. That can adapt browser-provided UI such as default form controls and scrollbars; it does not recolor every component you authored. The W3C CSS Color Adjustment Module describes this behavior and notes that scheme names do not specify an exact palette. Consult the W3C specification.

Add a light, dark, and system toggle

For an actual switch, three choices are clearer than a simple on/off control: System follows the device, while Light and Dark pin the page to a chosen mode. The example below stores only explicit light or dark selections; choosing System removes the saved override.

Apply the saved mode before the first paint

Keep the media-query baseline in CSS, then place this small script in the head after the color-scheme meta tag and before stylesheets or page content. It reads the saved choice and adds a root attribute before the page is painted, reducing the chance that a saved dark choice first appears in system light mode (or vice versa). If storage is unavailable, the CSS system default remains in place.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<meta name="color-scheme" content="light dark">
<script>
  (() => {
    let saved = null;
    try {
      saved = localStorage.getItem('theme');
    } catch (_) {
      // Storage may be unavailable; CSS will use the system preference.
    }

    if (saved === 'light' || saved === 'dark') {
      document.documentElement.dataset.theme = saved;
      document.querySelector('meta[name="color-scheme"]')
        ?.setAttribute('content', saved);
    }
  })();
</script>

For manual mode, update the CSS so explicit attributes take precedence over the system media query. Retain the media query as the fallback for system mode and when JavaScript is disabled.

Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
:root {
  color-scheme: light dark;
  --page: #fff;
  --surface: #f2f4f7;
  --text: #1b1d21;
  --muted: #555d69;
  --border: #c8ced8;
  --accent: #174ea6;
}

@media (prefers-color-scheme: dark) {
  :root {
    --page: #15171a;
    --surface: #22262b;
    --text: #f1f3f5;
    --muted: #c1c7d0;
    --border: #515965;
    --accent: #a9c7ff;
  }
}

:root[data-theme="light"] {
  color-scheme: light;
  --page: #fff;
  --surface: #f2f4f7;
  --text: #1b1d21;
  --muted: #555d69;
  --border: #c8ced8;
  --accent: #174ea6;
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --page: #15171a;
  --surface: #22262b;
  --text: #f1f3f5;
  --muted: #c1c7d0;
  --border: #515965;
  --accent: #a9c7ff;
}

Wire up an accessible, keyboard-operable control

A select element provides a clear accessible name, exposes the selected value, and works with the keyboard without extra interaction code. Put it in the page body. The handler updates the document attribute, updates the meta element to the selected scheme, and saves or clears the explicit value.

<label for="theme-choice">Color theme</label>
<select id="theme-choice">
  <option value="system">System</option>
  <option value="light">Light</option>
  <option value="dark">Dark</option>
</select>

<script>
  (() => {
    const root = document.documentElement;
    const meta = document.querySelector('meta[name="color-scheme"]');
    const control = document.getElementById('theme-choice');

    let saved = null;
    try {
      saved = localStorage.getItem('theme');
    } catch (_) {}

    control.value = saved === 'light' || saved === 'dark' ? saved : 'system';

    control.addEventListener('change', () => {
      const choice = control.value;
      if (choice === 'system') {
        delete root.dataset.theme;
        meta.setAttribute('content', 'light dark');
        try { localStorage.removeItem('theme'); } catch (_) {}
        return;
      }

      root.dataset.theme = choice;
      meta.setAttribute('content', choice);
      try { localStorage.setItem('theme', choice); } catch (_) {}
    });
  })();
</script>

The code uses document.documentElement.dataset.theme to store the active override in the root element. The stylesheet handles the visual presentation, while JavaScript updates preference state. If the visitor selects System, the override is removed and the media query takes over again.

Optionally respond to operating-system changes

When system mode is active, the CSS media query updates on its own. If JavaScript also needs to run behavior when the system setting changes, use matchMedia and subscribe to its change event. Do not let an OS change overwrite a saved light or dark choice.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const systemPreference = window.matchMedia('(prefers-color-scheme: dark)');

systemPreference.addEventListener('change', (event) => {
  const hasOverride =
    document.documentElement.dataset.theme === 'light' ||
    document.documentElement.dataset.theme === 'dark';

  if (!hasOverride) {
    // CSS already follows this preference. Update other system-dependent UI here.
    console.log(event.matches ? 'System is dark' : 'System is light');
  }
});

Google Chrome’s guidance recommends listening for the change event when JavaScript reads the system preference through matchMedia. The CSS-only baseline does not need this listener just to change colors.

Choose media-query tokens or light-dark()

Media-query token overrides are broadly useful as a baseline: they make the system-following behavior explicit and provide a fallback where newer CSS functions are unavailable. The light-dark() function can express a light and dark value in one declaration when the root’s color scheme is established, but do not make it your only implementation if older browsers matter.

Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.
Technique Useful for Fallback consideration
@media (prefers-color-scheme: dark) with custom properties System-aware palettes and broad fallback coverage Keep ordinary default values outside the media query
light-dark(light-value, dark-value) Compact declarations for paired values Retain fallback custom properties and media queries where unsupported

Google Chrome’s Modern Web Guidance reports color-scheme as Baseline since 2022-02-03, listing Chrome 98 (February 2022), Edge 98 (February 2022), Firefox 96 (January 2022), and Safari 13 (September 2019) as supporting releases. It reports light-dark() as Baseline since 2024-05-13, listing Chrome 123 (March 2024), Edge 123 (March 2024), Firefox 120 (November 2023), and Safari 17.5 (May 2024). Compatibility information can change, so check the current guidance and browser matrix before treating the newer function as a requirement.

Audit the dark presentation for accessibility and completeness

A mode switch is a presentation option, not proof that either presentation conforms to accessibility requirements. WAI’s C29 technique describes a style switcher as one way to provide alternate presentations; its techniques are examples, not mandatory approaches. Its test procedure checks that the control changes the presentation and that the resulting version meets the claimed conformance level. Read WAI’s C29 technique.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Check text against its actual background in both modes; do not assume that a dark palette is automatically more legible.
  • Inspect authored elements beyond body text: links, buttons, form fields, borders, focus indicators, code blocks, charts, illustrations, and selected or disabled states.
  • Use a visible focus indicator in both palettes and make the control operable by keyboard. Give it a clear accessible label and make its current selection apparent.
  • Check photographs, logos, and other images that may have transparent or white backgrounds; CSS cannot choose an appropriate alternative asset automatically.
  • Test browser-provided controls separately. color-scheme can adapt controls and scrollbars, but does not automatically restyle author-defined components.

The W3C CSS Color Adjustment specification explains that “light” and “dark” identify scheme families, not fixed colors. Set foreground and background together rather than relying on assumed browser color substitutions.

Account for embedded pages and browser differences

Embedded content can resolve theme preferences differently depending on the browser and embedding arrangement. Google Chrome’s guide reports that Chrome and Firefox pass the embedding element’s color scheme into iframes, while Safari resolves prefers-color-scheme to the system setting inside iframes. If you control both the parent and embedded page and need them to agree, send an explicit theme signal, such as a URL parameter or postMessage, and verify the behavior in the target browsers. Do not assume the parent’s manual override automatically propagates everywhere.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot common dark-mode switch problems

The switch changes but the page colors do not

Check that the handler writes exactly data-theme="light" or data-theme="dark" on the root element and that the CSS selectors use the same attribute values. Confirm that the affected elements use the theme tokens; fixed color declarations can override them.

Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient

The page flashes the wrong theme on reload

The saved preference is probably applied after the browser has already painted. Move the initialization script into the document head before styles and visible content, keep it small, and ensure it reads the same storage key the control writes. Keep the CSS system default so content still has a sensible theme if script execution fails.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Browser controls remain light in dark mode

Set color-scheme on the root and include the color-scheme meta tag. For a manual choice, update the meta content to the selected scheme; when following the system, leave both schemes declared. Remember that this informs browser-controlled UI, not every custom component.

Changing the system preference overrides a visitor’s choice

Do not let the matchMedia change handler write a system-derived value when an explicit saved override exists. CSS can continue to track the system in the absence of the root override.

The stored setting throws an error or is missing

Storage access can fail in some contexts. Wrap reads and writes in try/catch, as in the examples. If no valid saved value is available, omit the root override and let CSS follow the system preference.

Only some content looks correct

Search for hard-coded colors and assets that assume a light background. Replace repeated authored colors with theme tokens, then inspect each component and state in both schemes. A browser’s dark form controls do not fix a chart, code sample, or custom button whose colors are fixed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

Performance, reliability, and implementation cost

The CSS-only option adds no theme-selection JavaScript and can follow system changes through the media query. A manual override adds a small initialization and event handler plus storage access. Applying the saved mode early reduces visual mismatch, but no script-based preference should be the only source of a valid theme: keep the stylesheet’s system-aware baseline so a disabled script or unavailable storage does not leave the page unthemed.

For a small site, CSS variables and one control are usually sufficient. For a larger application, use shared design tokens so pages and components draw from the same palette, and test the whole interface rather than just the page shell. Neither the existence of dark mode nor the use of a dark background establishes that text contrast or other accessibility requirements are satisfied.

Or skip the browser setup

If you need a screenshot of a page in a theme rather than implementing the theme itself, ScreenshotNeo is a website screenshot API and MCP server for developers. It makes one GET request with a URL and returns a screenshot or PDF. Its clean-shot flow accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers.

For example, request an image of a page configured for dark mode:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" 
  -d access_key=YOUR_API_KEY 
  --data-urlencode url=https://example.com 
  -d color_scheme=dark 
  -o shot.webp

See the ScreenshotNeo documentation for supported parameters. The code above shows the one-call pattern with a target URL; use documented options for the capture you need. ScreenshotNeo also provides an MCP server for AI agents, with take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, no card required.

Frequently Asked Questions

What does the color-scheme meta tag do?

It tells the browser which schemes the page supports, helping browser-provided UI adapt. It does not style every page element.

Should a dark-mode toggle be a checkbox?

A labeled select with System, Light, and Dark makes the available choices explicit. A different control can work too if its name, state, keyboard behavior, and visible focus are clear.

Does dark mode automatically improve accessibility?

No. The colors and resulting presentation need to be evaluated; a toggle alone does not establish conformance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.