Frontend Master

JavaScript Curriculum

CSS Variables and Theming
+60 XP

CSS Variables and Theming

medium
~30 min·60 XP

The coffee shop brand is expanding. They want a dark mode, a seasonal theme, and consistent spacing across the whole site. CSS variables make this possible without rewriting a single component.

CSS Variables and Theming

CSS custom properties — usually called CSS variables — let you store values with a name and reuse them throughout your stylesheet. Change the value in one place, and it updates everywhere it's referenced.

Declaring and Using Variables

Variables are declared with -- prefix and accessed with var():

css-variables.css

Declare variables with -- prefix on :root. Use them anywhere with var(). Change once, update everywhere.

:root {
  --color-brand: #3b1f0e;
  --color-bg: #faf6f1;
  --radius: 8px;
  --spacing-md: 16px;
}

.button {
  background: var(--color-brand);
  border-radius: var(--radius);
  padding: var(--spacing-md);
}
ℹ️Why :root?
:root is the highest-level element (equivalent to html but with higher specificity). Declaring variables there makes them available everywhere in the document. Think of :root as your global design token store — colours, spacing, type scale, shadows.

Building a Theme System

Variables become a full theming system when you override them at a different selector:

theme-builder.css
Live preview
☕ The Grind
MenuAbout
Espresso
Specialty blend
Latte
Specialty blend
Today's special: Single-origin pour over
Generated CSS
:root {
  --brand: #3b1f0e;
  --brand-lt: #7a5c44;
  --bg: #faf6f1;
  --surface: #ffffff;
  --border: #e8ddd4;
  --text: #2c1810;
  --text-muted: #6b4c3b;
  --accent: #c8873a;
}
💡Design tokens — naming conventions
Name variables by role, not value. --color-brand instead of --dark-brown. --spacing-md instead of --16px. When you swap the coffee theme for ocean theme, --color-brand still makes sense — --dark-brown doesn't. Role-based naming is the foundation of a scalable design system.

Dark Mode with CSS Variables

CSS variables make dark mode trivially easy — just override the tokens:

dark-mode.css

Add/remove a .dark class on <html>. Works everywhere, easily overridable.

Live preview
☕ The GrindMenu · About
Espresso
Rich, concentrated shot. £2.50
CSS
:root {
  --bg: #ffffff;
  --text: #1a1a1a;
  --surface: #f5f5f5;
}

html.dark {
  --bg: #0d1117;
  --text: #c9d1d9;
  --surface: #161b22;
}
JS
// Toggle dark mode
document.documentElement
  .classList.toggle('dark')

// Persist preference
localStorage.setItem('theme',
  isDark ? 'dark' : 'light')
⚠️Combine class toggle with prefers-color-scheme
The best dark mode: use prefers-color-scheme as the default automatic behaviour, AND support a manual class toggle so users can override their OS setting. Store the preference in localStorage and apply it before the page renders to avoid a flash.

Your Challenge

Refactor the coffee shop page with a full CSS variable system and a working dark mode toggle.

Challenge

Refactor the coffee shop page to use CSS variables for all colours, spacing, and border-radius. Define them in :root. Then add a dark mode using html.dark variable overrides and a JavaScript button to toggle the class.

css-variablescustom-propertiesvar():rootthemingdark-modeprefers-color-schemedesign-tokensfallback-valuesscoped-variables
CSS Variables and Theming | Nexus Learn