Frontend Development 25 min read

Mastering Dark Mode: CSS & JavaScript Techniques for Modern Web Design

This article explains why dark mode has become a web design priority, describes the system‑level nature of dark/light themes, and provides practical CSS and JavaScript solutions—including media queries, custom properties, color‑scheme, filters, mix‑blend‑mode, and transition effects—to implement seamless dark mode support across browsers.

Taobao Frontend Technology
Taobao Frontend Technology
Taobao Frontend Technology
Mastering Dark Mode: CSS & JavaScript Techniques for Modern Web Design
Dark mode became a hot topic after macOS introduced a system‑wide dark theme, and developers have been discussing various ways to add dark mode to websites. This article revisits the topic from multiple angles, offering practical implementations.

Dark Mode Is System‑Level

Dark mode is not a new concept; it has existed for a long time. Modern operating systems like macOS let users switch between dark and light skins at the system level, and any application that respects the system setting can automatically follow.

Because dark mode benefits users with visual impairments such as color blindness, web sites aim to align with the system‑level preference by providing a dark theme.

Implementation Principle

Providing dark mode is essentially offering two style sheets (e.g.,

theme1.css

and

theme2.css

) and letting the user or the system choose which one to apply.

Basic JavaScript Switch

<code>&lt;!-- HTML --&gt;
&lt;link rel="stylesheet" href="../theme1.css" id="theme_css" /&gt;

&lt;script&gt;
  document.getElementById('buttonID').addEventListener('click', function(){
    document.getElementById('theme_css').href = '../theme2.css';
  });
&lt;/script&gt;</code>

CSS Implementation of Dark Mode

Modern browsers support the

prefers-color-scheme

media query, which detects the user’s OS theme preference.

<code>@media (prefers-color-scheme: dark) {
  :root {
    --background-color: #111416;
    --text-color: #ccc;
    --link-color: #f96;
  }
}

:root {
  --background-color: #fff;
  --text-color: #333;
  --link-color: #b52;
}

body { background-color: var(--background-color); color: var(--text-color); }
a { color: var(--link-color); }</code>

To detect browser support:

<code>if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
  console.log('Browser supports dark mode');
}</code>

Reduced‑Motion Preference

The

prefers-reduced-motion

media query can disable animations for users who request less motion.

<code>@media (prefers-reduced-motion: reduce) {
  button { animation: none; }
}

@media (prefers-reduced-motion: no-preference) {
  button { animation: vibrate 0.3s linear infinite both; }
}</code>

New CSS Feature: color-scheme

The

color-scheme

property informs the browser about the page’s supported color schemes, allowing native form controls to adapt.

<code>/* style.css */
:root { color-scheme: light dark; }

body { color: var(--color); background-color: var(--background-color); }</code>

Image and Icon Handling

In dark mode, images may need brightness or contrast adjustments. Simple CSS can be used:

<code>@media (prefers-color-scheme: dark) {
  img { filter: brightness(.8) contrast(1.2); }
  img:not([src*=".svg"]) { filter: brightness(.8) contrast(1.2); }
}</code>

For SVG icons, use

currentColor

so the icon inherits the text color.

<code>&lt;svg fill="none" stroke="currentColor" ...&gt; ... &lt;/svg&gt;</code>

Filter and Mix‑Blend‑Mode Hacks

When native media queries are unavailable, CSS filters or

mix-blend-mode

can simulate dark mode.

<code>.theme-dark { filter: invert(100%) hue-rotate(180deg); }
.theme-dark img { filter: invert(100%) hue-rotate(180deg); }

.dark-mode-screen {
  position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;
  background: white; mix-blend-mode: difference;
}</code>

Smooth Transition Between Themes

Adding a CSS transition to color variables creates a smooth switch.

<code>body {
  --duration: 0.5s; --timing: ease;
  color: var(--color);
  background-color: var(--background-color);
  transition: color var(--duration) var(--timing),
              background-color var(--duration) var(--timing);
}</code>

JavaScript Dark/Light Toggle

JavaScript can listen to the

prefers-color-scheme

media query and toggle CSS files or custom properties accordingly.

<code>const mq = window.matchMedia('(prefers-color-scheme: dark)');
mq.addEventListener('change', e => {
  console.log(`Dark mode is ${e.matches ? 'on' : 'off'}.`);
});</code>

While a pure‑CSS solution is preferred, a JS toggle can provide a manual switch or time‑based switching.

Browser Configuration Tips

In Firefox, set

ui.systemUsesDarkTheme

to

1

via

about:config

. In Safari, use the built‑in developer tools to preview dark mode. Extensions like Dark Reader can force dark mode on sites that lack native support.

Conclusion

There is no one‑size‑fits‑all solution for dark mode. Developers should choose the approach that best fits their project—whether pure CSS, CSS + JS, or system‑level integration—while paying attention to color contrast, image handling, and accessibility.

JavaScriptweb developmentcssdark modeprefers-color-scheme
Taobao Frontend Technology
Written by

Taobao Frontend Technology

The frontend landscape is constantly evolving, with rapid innovations across familiar languages. Like us, your understanding of the frontend is continually refreshed. Join us on Taobao, a vibrant, all‑encompassing platform, to uncover limitless potential.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.