← Back to CSS Course | Chapter 8: Animations & Effects | Lesson 22 of 22

CSS Custom Properties

Imagine designing a house. You decide to use a specific, custom shade of blue paint for your living room walls, kitchen cabinets, and front door. If you buy standard paint cans, you have to repaint every single surface manually if you decide to change colors later. Now, imagine using a smart paint system. You mix your custom color in one central tank, give it a name (like '--accent-color'), and link your paint brushes to that tank. To change your accents from blue to green, you simply change the color in that one central tank, and all your surfaces update automatically.
Syntax
css
:root {
  --custom-property: value;
}
selector {
  property: var(--custom-property);
}

Variables vs. Preprocessor Variables

Unlike preprocessor variables (like Sass or Less) which are compiled and hardened into static CSS before reaching the browser, native CSS custom properties are dynamic. They live inside the browser's live DOM, meaning you can read, update, and manipulate them in real-time.

Note:
  • Use native CSS variables instead of preprocessor variables to support live, dynamic page overrides natively.
  • Accepted values:
  • name: <value> — declares a custom property
  • var(--name) — reads the property
  • var(--name, fallback) — reads with a fallback value
  • initial — resets a custom property to guaranteed-invalid
Warning: Ensure your custom variable names always start with double hyphens (e.g., --main-color) to comply with browser standards.

Example: Variables vs. Preprocessor Variables

css
<style>
:root {
  --main-color: teal;
}
p {
  color: var(--main-color);
}
</style>
<p>A live, native CSS variable, not a compiled preprocessor one</p>

Dynamic Updates with JavaScript

Because native CSS variables are part of the DOM, you can easily read, modify, and update their values in real-time using simple JavaScript scripts, allowing you to build rich, interactive user settings.

Note:
  • Use JavaScript to update your CSS variables dynamically inside your user interaction handlers.
  • Accepted values:
  • element.style.setProperty('--name', value) — sets it from JavaScript
  • getComputedStyle(el).getPropertyValue('--name') — reads it
  • style.removeProperty('--name') — removes it
  • var(--name) — CSS picks up the change
Warning: Ensure your script targets the correct CSS variable name case-sensitivity exactly to prevent broken overrides.

Example: Dynamic Updates with JavaScript

css
<style>
:root {
  --highlight: yellow;
}
.box {
  background: var(--highlight);
}
</style>
<div class="box" onclick="document.documentElement.style.setProperty('--highlight', 'pink')">Click to update --highlight live</div>

Variable Inheritance and Cascading

CSS variables follow standard CSS inheritance and cascading rules. When declared inside a specific selector instead of :root, the variable is local and only accessible to that element and its children.

Note:
  • Use local, scoped variables to keep your component styles encapsulated and modular.
  • Accepted values:
  • name declared on :root — available everywhere
  • name declared on a class — scoped to that subtree
  • var(--name, fallback) — falls back if undefined
  • inherits automatically — custom properties inherit by default
Warning: Attempting to reference local variables outside of their parent container scope will fail.

Example: Variable Inheritance and Cascading

css
<style>
.card {
  --card-bg: navy;
  background: var(--card-bg);
}
</style>
<div class="card">Local variable, scoped to this element and its children</div>

Standard Layout Theming Systems

CSS variables make it easy to build dynamic website theme changers. By defining your page color variables inside :root and updating them under a custom class (like '.dark-mode'), you can toggle themes instantly.

Note:
  • Use custom data attributes combined with variables to make toggling themes cleanly.
  • Accepted values:
  • name: <value> on :root — global tokens
  • [data-theme="dark"] { --name: ... } — theme override
  • var(--name) — consumption
  • var(--name, fallback) — safe default
Warning: Ensure your color variables maintain high contrast in both themes to keep your content readable.

Example: Standard Layout Theming Systems

css
<style>
:root {
  --bg: white;
}
.dark-mode {
  --bg: black;
  background: var(--bg);
  color: white;
}
</style>
<div class="dark-mode">Theme toggled by swapping one variable</div>

Designing Dark Mode Schemas

You can design your dark mode theme to activate automatically based on the user's system preferences using the prefers-color-scheme media query, updating your color variables inside the query cleanly.

Note:
  • Combine prefers-color-scheme media queries with your CSS variables to build automated dark mode themes easily.
  • Accepted values:
  • :root { --bg: ...; } — light tokens
  • @media (prefers-color-scheme: dark) — dark tokens
  • [data-theme="dark"] — manual override
  • color-scheme: light dark — native controls follow
Warning: Make sure your text color variables are updated along with your backgrounds to prevent unreadable dark-on-dark text.

Example: Designing Dark Mode Schemas

css
<style>
:root {
  --bg: white;
  --text: black;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: black;
    --text: white;
  }
}
body {
  background: var(--bg);
  color: var(--text);
}
</style>
<p>Activates automatically from system preferences</p>
Live Example
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Forgetting to write the double hyphen prefix (--) when naming or calling custom CSS variables.
  2. Attempting to reference local, scoped variables outside of their parent container scope.
  3. Misspelling variable names, which are case-sensitive.
Chapter Summary
  • Native CSS custom properties are dynamic variables that remain active and editable inside the browser's live DOM.
  • Read and update your CSS variables dynamically inside your JavaScript scripts to build interactive layouts easily.
  • Leverage prefers-color-scheme media queries and variables to build automated dark mode themes cleanly.
Browser Support

Standard CSS custom properties (variables) are supported natively by all modern web browsers.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.