The most maintainable way to implement dark mode is to define semantic color tokens, let prefers-color-scheme select the system preference, and set color-scheme: light dark so browser controls follow your palette. Add JavaScript only when visitors need a saved Light/Dark/System choice.
Start with a CSS-first theme
prefers-color-scheme exposes the light or dark preference supplied by a user agent or operating system; it does not create a palette for your site. Your CSS must define the colors and states. The following pattern keeps component styles independent of the actual colors.
:root {
color-scheme: light dark;
--page-bg: #ffffff;
--page-fg: #202124;
--surface: #f3f4f6;
--border: #c7cbd1;
--accent: #1558a6;
--accent-visited: #6339a5;
--focus: #0b57d0;
}
@media (prefers-color-scheme: dark) {
:root {
--page-bg: #17191c;
--page-fg: #f2f3f5;
--surface: #24272b;
--border: #555b63;
--accent: #9fc5ff;
--accent-visited: #d0b4ff;
--focus: #8ab4f8;
}
}
* { box-sizing: border-box; }
body {
margin: 0;
color: var(--page-fg);
background: var(--page-bg);
font-family: system-ui, sans-serif;
}
.card {
background: var(--surface);
border: 1px solid var(--border);
}
a { color: var(--accent); }
a:visited { color: var(--accent-visited); }
:focus-visible {
outline: 3px solid var(--focus);
outline-offset: 2px;
}
The values above are illustrative, not an accessibility audit. Validate foreground/background pairs with your real fonts, sizes, disabled states, hover states, and content. “Dark” can be charcoal, navy, or another low-luminance palette; it does not require black backgrounds and white text. The W3C CSS Color Adjustment specification explains that scheme names do not guarantee a particular contrast level: W3C CSS Color Adjustment.
Tell the browser about its own controls
The root declaration lets the browser adapt controls such as scrollbars, form widgets, and selection UI. Also place this in the document <head>, before linked stylesheets where possible:
Recommended Free Tools
#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
<meta name="color-scheme" content="light dark">
MDN notes that early placement helps the user agent choose its initial treatment before CSS finishes loading: MDN color-scheme. The W3C specification defines the underlying behavior at w3.org/TR/css-color-adjust-1.
How to make a page follow the operating-system preference
With the CSS above, no JavaScript is required. When the visitor changes the operating-system or browser theme, the media query reevaluates and your tokens switch. Keep the default palette explicit rather than relying on inherited system colors so every component has a deliberate result. The media feature is documented at MDN prefers-color-scheme.
Apply tokens to every surface, not just body. Audit navigation, cards, code blocks, tables, placeholders, error messages, borders, icons, charts, images, dialogs, and third-party widgets. A hard-coded white panel or gray text can become the least readable element in dark mode.
How to add a dark-mode toggle
A toggle is optional. Use it when the product needs a site-level choice that can differ from the device setting. The robust model has three states: System (no override), Light, and Dark. If your interface only needs an on/off switch, label the two states clearly and explain whether “off” means Light or System.
Use an attribute as the override contract
Keep the system fallback in CSS, then override tokens when the document has a theme attribute:
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
:root[data-theme="light"] {
color-scheme: light;
--page-bg: #ffffff;
--page-fg: #202124;
--surface: #f3f4f6;
--border: #c7cbd1;
--accent: #1558a6;
--accent-visited: #6339a5;
--focus: #0b57d0;
}
:root[data-theme="dark"] {
color-scheme: dark;
--page-bg: #17191c;
--page-fg: #f2f3f5;
--surface: #24272b;
--border: #555b63;
--accent: #9fc5ff;
--accent-visited: #d0b4ff;
--focus: #8ab4f8;
}
Place the attribute on <html>, not only on a nested app element, so browser UI and the entire document receive the same scheme.
Apply a saved choice before painting
Put this small inline script before your main stylesheet or bundled application script. It reads only the two deliberate overrides; an absent value leaves the CSS media query in control.
<script>
(() => {
const saved = localStorage.getItem('theme');
if (saved === 'light' || saved === 'dark') {
document.documentElement.dataset.theme = saved;
}
})();
</script>
This reduces a flash of the wrong palette on repeat visits. Storage can be unavailable in privacy-restricted contexts, so the CSS-only system behavior must remain a valid fallback.
Wire the control and persistence
<label for="theme-select">Theme</label>
<select id="theme-select">
<option value="system">System</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
<script>
const root = document.documentElement;
const select = document.querySelector('#theme-select');
const media = window.matchMedia('(prefers-color-scheme: dark)');
function applyTheme(value) {
if (value === 'light' || value === 'dark') {
root.dataset.theme = value;
localStorage.setItem('theme', value);
} else {
delete root.dataset.theme;
localStorage.removeItem('theme');
}
}
const saved = localStorage.getItem('theme');
select.value = saved === 'light' || saved === 'dark' ? saved : 'system';
select.addEventListener('change', () => applyTheme(select.value));
media.addEventListener?.('change', () => {
if (!localStorage.getItem('theme')) {
// The CSS media query updates automatically; this hook is useful
// if JavaScript-rendered colors or charts need redrawing.
document.dispatchEvent(new CustomEvent('system-theme-change'));
}
});
</script>
When an explicit override exists, a system change should not replace it. When the visitor returns to System, remove the attribute and storage key so CSS follows the current preference. If JavaScript renders charts, canvas graphics, syntax highlighting, or inline SVG colors, redraw those assets when the media query changes.
Preventing flashes and keeping the page stable
- Put the
color-schememeta tag before CSS links. - Run the storage-reading bootstrap before the first paint where practical.
- Do not wait for a client-side framework hydration cycle to decide the initial theme.
- Keep both palettes in CSS so a blocked or failed script still produces a usable page.
- Use the same token names in server-rendered HTML and hydrated components.
Chrome’s modern web guidance covers the system fallback, early override application, and reacting to preference changes: Google Chrome modern web guidance.
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
Choosing between implementation approaches
| Approach | Strength | Trade-off | Best fit |
|---|---|---|---|
CSS prefers-color-scheme |
Minimal code and automatic system matching | No site-specific choice | Content sites that should follow the device |
| CSS tokens plus JavaScript override | Persistent Light/Dark/System control | Needs early state handling and change behavior | Applications with user preferences |
light-dark() plus fallback |
Compact paired color declarations | Requires support checks and a fallback for older browsers | Projects targeting current browsers |
Using light-dark() without abandoning older browsers
The light-dark() function selects one of two colors according to the active color-scheme:
:root {
color-scheme: light dark;
--page-bg: light-dark(#fff, #17191c);
--page-fg: light-dark(#202124, #f2f3f5);
}
Retain the media-query/token fallback when older browser versions matter. Chrome’s guidance lists light-dark() as newly available from May 13, 2024, while it lists color-scheme as widely available from February 3, 2022. MDN describes prefers-color-scheme as widely available across many devices and browser versions since January 2020. These are documentation dates, not a guarantee for every browser version you support; verify your target matrix in MDN’s compatibility data and the Chrome guidance.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Embedded content, SVG, and iframes
Embedded SVG and iframe documents can respond to a parent color scheme in applicable contexts, as MDN describes. Cross-origin embeds may not share your tokens, and a provider can hard-code its own colors. Chrome’s guidance notes a Safari difference: Safari resolves the preference inside an iframe from the system setting rather than the embedding context. If you control both documents, pass an explicit theme through a supported application mechanism and test it in the browsers you target. See MDN’s embedded-content notes and the Chrome guidance.
Accessibility and visual QA checklist
- Check normal text, large text, icons, placeholders, disabled controls, links, visited links, and error text in both schemes.
- Test keyboard focus, hover, active, selected, expanded, and validation states; never rely on color alone.
- Inspect borders and separators at normal display brightness and on low-quality screens.
- Verify logos, photographs, illustrations, syntax highlighting, charts, and screenshots; provide dark-safe variants or backgrounds where necessary.
- Test zoom, forced colors, high-contrast settings, reduced motion, and a keyboard-only workflow.
- Check dialogs, menus, browser autofill, date pickers, and scrollbars after declaring
color-scheme. - Use a contrast checker for the actual font sizes and weights. The W3C WAI C23 page is a technique example—not a blanket conformance claim—about allowing user-agent preferences: WAI C23.
Common failures and fixes
The page changes, but cards stay white
Find hard-coded background, color, gradients, and inline styles. Replace them with semantic variables. Also inspect component-library defaults and shadow DOM, which may require component-specific theme inputs.
The toggle flashes the wrong theme
Move the storage bootstrap into the document head before the stylesheet or render, and keep the meta color-scheme declaration early. Avoid waiting for asynchronous configuration or hydration.
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
Forms look inconsistent
Ensure the root declares both supported schemes and check native controls in each browser. Explicitly style labels, placeholders, borders, validation messages, and focus indicators instead of assuming the browser will infer your design.
System changes are ignored
When no manual override is saved, CSS should update automatically. If JavaScript-rendered content remains stale, retain a matchMedia('(prefers-color-scheme: dark)') listener and redraw that content. Do not apply the listener’s result over a deliberate Light or Dark choice.
An iframe has the wrong theme
Confirm whether the embedded document owns its CSS and whether it is same-origin. For an application you control, send the selected theme explicitly; do not assume Safari and other browsers resolve iframe preferences identically.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
To inspect how your dark mode renders at a URL, ScreenshotNeo can capture a clean screenshot or PDF through one request. Its consent step accepts cookie banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.
Use the API documentation at screenshotneo.com/docs/ for all options, including viewport and device presets, dark-mode capture, full-page lazy-image loading, CSS selectors, custom CSS and JavaScript, waits, request blocking, cookies, headers, geolocation, resizing, caching, signed links, PDFs, asynchronous jobs, and bulk capture.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallcurl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o dark-mode.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
r.raise_for_status()
open("dark-mode.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('dark-mode.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo also provides an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000, every feature is on every plan, and yearly billing gives two months free. Sign up free for ScreenshotNeo.
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
FAQ
Does dark mode require JavaScript?
No. A prefers-color-scheme media query and semantic CSS tokens are sufficient when the page should follow the system preference.
Should the default be light or dark?
Neither is universally correct. Define a deliberate light palette, a deliberate dark palette, and let the visitor’s preference choose unless your product has a documented reason to do otherwise.
Can I store the choice in cookies instead of localStorage?
Yes. Cookies are useful when the server must render the selected theme, but they add request and privacy considerations. Whichever storage you choose, apply the value before the first paint and preserve System as an unset override.
Free tools Windows power users keep installed
One-click scans. No signup required.
Frequently Asked Questions
Does dark mode require JavaScript?
No. A prefers-color-scheme media query and semantic CSS tokens are sufficient when the page should follow the system preference.
Should the default be light or dark?
Neither is universally correct. Define a deliberate light palette, a deliberate dark palette, and let the visitor’s preference choose unless your product has a documented reason to do otherwise.
Can I store the choice in cookies instead of localStorage?
Yes. Cookies are useful when the server must render the selected theme, but they add request and privacy considerations. Apply the value before first paint and preserve System as an unset override.
Quick Recap
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.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →

