CSS 3 min read

CSS Variables and Dark Mode: How to Theme a Website

CSS custom properties make theming easy — brand colours, spacing and a full dark mode from one set of tokens. Here's the exact approach used on this site, including a no-flash theme switcher.

On this page

Key takeaways

  • CSS custom properties (variables) like --brand let you define colours once and reuse them everywhere.
  • Dark mode becomes a matter of swapping variable values — not rewriting every rule.
  • Respect the visitor’s system preference, offer a manual toggle, and prevent the “flash” of the wrong theme on load.

This website has a light and dark theme that follows your device setting and remembers your choice. Behind it is a simple pattern: design tokens in CSS variables, a data-theme attribute on the <html> element, and a tiny script that runs before the page paints. Here’s how to build the same thing.

CSS custom properties in 60 seconds#

:root {
  --brand: #7ed957;
  --text: #0f172a;
  --bg: #f7f8fb;
  --radius: 16px;
}
.button { background: var(--brand); border-radius: var(--radius); }
body    { color: var(--text); background: var(--bg); }

Variables cascade and inherit like normal properties, can be changed at any level (.card { --radius: 8px; }) and can be updated with JavaScript at runtime — unlike Sass variables, which disappear at build time.

Design tokens: name by role, not by colour#

Avoid Prefer Why
--white --surface The surface is dark in dark mode
--dark-grey --text, --muted Describes purpose
--green --brand, --on-brand Brand can change; text on it needs contrast

The dark theme#

:root {
  --bg: #f7f8fb; --surface: #ffffff; --text: #0f172a; --muted: #5b6477;
  --line: rgba(15, 23, 42, .09);
  color-scheme: light;
}
[data-theme="dark"] {
  --bg: #0b0d12; --surface: #12151d; --text: #e8eaf0; --muted: #98a2b3;
  --line: rgba(255, 255, 255, .08);
  color-scheme: dark;
}

color-scheme tells the browser to style scrollbars, form controls and default backgrounds to match.

Respect the system preference#

CSS can detect the operating system setting with @media (prefers-color-scheme: dark). To combine it with a manual toggle, resolve the preference in JavaScript and set data-theme:

<script>
(function () {
  try {
    var saved = localStorage.getItem('theme');
    var mode = saved || (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
    document.documentElement.setAttribute('data-theme', mode);
  } catch (e) {}
})();
</script>
Prevent the flash Put this script inline at the very top of the <head>, before stylesheets. If it runs later (e.g. deferred), dark-mode users see a white flash on every page load.

Need a hand with this?

Get a quick, honest review of your website’s SEO.

Chat on WhatsApp

The toggle button#

<button type="button" id="theme-toggle" aria-label="Switch to dark mode">🌙</button>
<script>
document.getElementById('theme-toggle').addEventListener('click', function () {
  var root = document.documentElement;
  var next = root.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
  root.setAttribute('data-theme', next);
  try { localStorage.setItem('theme', next); } catch (e) {}
  this.setAttribute('aria-label', next === 'dark' ? 'Switch to light mode' : 'Switch to dark mode');
});
</script>

Dark mode design tips#

  • Don’t use pure black backgrounds with pure white text — slightly softer values reduce glare.
  • Express elevation with lighter surfaces, not heavier shadows.
  • Brand colours may need adjusting: a dark green that works on white can disappear on black. This site uses its logo green as an accent in dark mode and near-black accents in light mode.
  • Logos with dark text need a light version (or an SVG using currentColor).
  • Check contrast in both themes (4.5:1 for text).
  • Update <meta name="theme-color"> so the mobile browser bar matches.

Bonus: color-mix() for derived colours#

--brand-soft: color-mix(in oklab, var(--brand) 12%, var(--surface));

One brand variable can generate soft backgrounds, borders and hover states that automatically adapt to light and dark surfaces.

Dark mode FAQ#

Does dark mode affect SEO?#

No. Search engines render your default styles. Dark mode is a user experience feature.

Should dark mode be the default?#

Follow the visitor’s system preference by default and let them override it.

Can I add dark mode to an existing WordPress theme?#

Yes, if the theme uses CSS variables; otherwise it requires overriding many rules. Some plugins offer automatic dark modes, with mixed results.

Found this useful? Share it

Join the discussion

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

Security code image. If you cannot read it, press refresh or contact me on WhatsApp.