Layout
CSS Variables
Master CSS Custom Properties (Variables), covering declaration scopes, root inheritance, dynamic changes via JavaScript, and theme styling.
1. Learning Objectives
In this lesson, you will master CSS Custom Properties. By the end of this topic, you will be able to:
- Declare global custom properties inside the
:rootpseudo-class. - Reference custom properties using the
var()function with fallbacks. - Explain the difference between global and local variable scope.
- Build dynamic light/dark color theme switchers using variables.
- Update custom properties dynamically using JavaScript.
2. Overview
CSS Variables (Custom Properties) allow you to store and reuse values across your stylesheets. Unlike preprocessor variables (like SCSS), CSS variables exist in the browser DOM, respect the cascade, and can be updated dynamically at runtime using JavaScript or media queries.
3. Why This Topic Matters
CSS variables make stylesheets easier to maintain and enable dynamic features:
- Simplifies Dark Mode: Instead of overriding colors on dozens of individual elements, you can define colors as variables in a single place (e.g.
:root) and update them with a single class change on the body. - Typo Prone Fallbacks: If you reference a variable that hasn't been declared, the property falls back to the browser default, which can break styles. Setting fallback values inside the
var()function prevents this.
4. Real-World Analogy
Think of CSS custom properties like **assigning roles in a theater script**:
- The Role (Variable Name): Creating a role named
--main-actor. In the script, actors reference this role without hardcoding specific names. - The Cast Member (Variable Value): Assigning an actor (e.g. "John") to play
--main-actor. If John gets sick, you swap in a new actor at the top of the cast list (the root stylesheet), updating all references automatically. - Local Role (Scope Override): A scene where a local stand-in actor plays the role of
--main-actoronly within a specific scene box, without affecting the rest of the play.
5. Core Concepts
CSS variables follow cascade and inheritance rules:
- Global Scope (:root): Variables declared inside the
:rootselector are available globally across the entire document. - Local Scope: Variables declared inside a specific selector (e.g.
.card) are available only to that element and its children. - var() Fallbacks: The second parameter inside the
var()function acts as a fallback value if the custom property is not defined.
| Scope Tier | Selector Target | Visibility Range |
|---|---|---|
| Global (:root) | :root (maps to `<html>`) |
Visible to all elements across the entire document. |
| Local Selector | Component class (e.g. .sidebar-card) |
Visible only to the target component and its children. |
6. Syntax & API Reference
Custom property names must start with double hyphens (--):
7. Visual Diagram
This diagram displays how CSS variable values inherit and cascade:
8. Live Example — Full Working Code
A sample HTML document showcasing how custom properties are used to build light and dark color themes:
9. Interactive Playground
Try It Yourself Challenges:
- Click the toggle button in the live example to test switching between light and dark mode colors.
- Add a local variable override inside a class selector rule (e.g.
.box { --accent-color: red; }) and notice if child elements inherit the overridden value.
10. Common Mistakes
| Mistake | Why it happens | Wrong | Correct |
|---|---|---|---|
| Missing double hyphens | Forgetting to start variable declarations with double hyphens (--). | :root { main-color: blue; } |
:root { --main-color: blue; } |
| Mismatched casing references | Forgetting that CSS variables are case-sensitive, leading to unrecognized variable names. | --accentColor: red; |
--accentColor: red; |
11. Best Practices
- Use semantic variable names: Choose names that describe the variable's role (e.g.
--color-primary) rather than its current value (e.g.--color-blue) to make the code easier to update. - Declare variables globally in :root: Define core design variables (colors, typography, spacing) inside the
:rootselector so they are available globally. - Always provide fallback values: Use fallbacks inside the
var()function (e.g.var(--primary-color, blue)) to prevent styling breaks if variables are missing. - Leverage variables for theme setups: Use variables to manage the colors and spacing values of key design elements to support light/dark modes and theming.
12. Browser Compatibility
| Feature | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| CSS Custom Properties support | Supported (49+) | Supported (31+) | Supported (9.1+) | Supported (15+) |
13. Interview Questions
🟢 Q1: How do browser-native CSS variables differ from preprocessor variables (like SCSS or Less)?
Answer: SCSS/Less variables are compiled into static values before the stylesheet is sent to the browser. As a result, they do not exist in the DOM and cannot be modified dynamically at runtime. Native CSS variables exist in the DOM, respect the cascade, can be updated dynamically using JavaScript, and can react to media queries.
14. Debugging Exercise
Identify why the badge color remains transparent, and fix the CSS configuration:
Diagnosis: The variable declaration uses --badgecolor, but the CSS rule references it using a hyphenated name --badge-color. Because CSS variables are case-sensitive and match character-for-character, the reference fails, and the background falls back to the default transparent state. To fix this, align the variable name and reference.
Fixed CSS:
15. Practice Exercises
Exercise 1: Dynamic Box Sizer
Build a box element whose dimensions are controlled by a variable (e.g. --box-size: 100px;). Write a CSS rule that increases this variable size on hover.
16. Scenario-Based Challenge
The Multi-Theme Theming Engine Challenge:
An enterprise portal needs to support Light, Dark, and High-Contrast themes to comply with accessibility requirements. Hardcoding colors in separate stylesheets is difficult to manage. Propose a CSS variables approach to implement these themes in a single stylesheet.
17. Quick Quiz
Q1: Which selector is standard for declaring global, document-wide CSS variables?
A) body
B) :root
C) html
Answer: B — The :root pseudo-class targets the root element (html) and is used to declare global variables.
18. Summary & Key Takeaways
- • CSS custom properties start with double hyphens (--) and are referenced using the var() function.
- • Custom properties can be updated dynamically in real-time using media queries or JavaScript.
19. Cheat Sheet
| Property API | Visual Layout Action |
|---|---|
element.style.setProperty('--name', val); |
Updates a CSS custom property value dynamically using JavaScript. |