Skip to content
CSS Variables (Custom Properties) — Complete Guide

CSS Variables (Custom Properties) — Complete Guide

DodaTech Updated Jun 6, 2026 8 min read

CSS variables (officially called custom properties) let you store values in one place and reuse them throughout your stylesheet. Change the variable, and every rule that uses it updates automatically. They make theming, maintenance, and responsive design dramatically simpler.

What You’ll Learn

By the end of this tutorial, you’ll declare CSS variables with -- prefix, access them with var(), understand scope and inheritance, create dark mode themes, use variables in calc() and media queries, and read/write them with JavaScript.

Prerequisite: You should understand CSS selectors and the cascade. CSS Selectors and CSS Cascade cover what you need.

Where This Fits

    flowchart LR
    A["Positioning & Layout"] --> B["**CSS Variables**"]
    B --> C["Flexbox"]
    C --> D["Grid"]
    D --> E["Responsive Design"]
    style B fill:#f97316,stroke:#c2410c,color:#fff
    style A fill:#e5e7eb,stroke:#9ca3af,color:#374151
    style E fill:#22c55e,stroke:#16a34a,color:#fff
  

Declaration and Usage

CSS variables are declared with a double dash (--) prefix and accessed with the var() function:

:root {
  --primary: #3498db;
  --spacing: 16px;
  --radius: 8px;
}

.button {
  background: var(--primary);
  padding: var(--spacing);
  border-radius: var(--radius);
}

Why :root? :root is the highest-level element (<html>). Declaring variables there makes them available everywhere — like global variables in programming.

Providing Fallbacks

.button {
  /* Use --button-bg if defined, otherwise default to #3498db */
  background: var(--button-bg, #3498db);

  /* Multiple fallback levels */
  padding: var(--spacing, var(--default-spacing, 16px));
}

Why fallbacks matter: If a variable isn’t defined (typo, missing declaration), the fallback kicks in. Without a fallback, the property becomes initial (e.g., background disappears).


Scope — Variables Inherit Through the DOM

Variables cascade just like other CSS properties. Declare them at different levels for different scopes:

:root {
  --accent: blue;          /* Global — available everywhere */
}

.card {
  --accent: red;           /* Overrides :root for .card and its children */
  background: var(--accent);  /* red */
}

.card .title {
  color: var(--accent);    /* red (inherits from .card) */
}

.other {
  background: var(--accent);  /* blue (from :root — no .card in ancestors) */
}

This is the power of scope: A component can set its own variable values without affecting other components. It’s like local vs global variables in JavaScript.


Theming — Dark Mode with Variables

Variables make theming trivial. Define your theme variables once, and change them with a class:

:root {
  --bg: #ffffff;
  --text: #1a202c;
  --primary: #3498db;
  --border: #e2e8f0;
}

.dark {
  --bg: #1a202c;
  --text: #e2e8f0;
  --primary: #63b3ed;
  --border: #2d3748;
}

body {
  background: var(--bg);
  color: var(--text);
  transition: background 0.3s, color 0.3s;
}

.card {
  border: 1px solid var(--border);
}
<body>
  <button onclick="document.body.classList.toggle('dark')">Toggle Dark Mode</button>
  <!-- Everything updates automatically -->
</body>

No media queries needed for theme switching. Just toggle a class and all variables update instantly.


Variables in calc()

Variables work seamlessly inside calc():

:root {
  --gap: 8px;
}

.grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: 1fr 1fr;
  padding: calc(var(--gap) * 2);    /* 16px */
}

.card {
  width: calc(100% - var(--gap) * 4);  /* 100% - 32px */
}

Variables in Media Queries

One pattern that’s especially useful: change variables at breakpoints instead of repeating selectors:

:root {
  --font-size: 1rem;
  --columns: 2;
  --gap: 8px;
}

@media (min-width: 768px) {
  :root {
    --font-size: 1.125rem;
    --columns: 3;
    --gap: 16px;
  }
}

@media (min-width: 1024px) {
  :root {
    --font-size: 1.25rem;
    --columns: 4;
    --gap: 24px;
  }
}

.grid {
  display: grid;
  grid-template-columns: repeat(var(--columns), 1fr);
  gap: var(--gap);
  font-size: var(--font-size);
}

This keeps your component styles clean — no media queries scattered through .grid styles. All breakpoint logic is centralized in :root.


JavaScript Access — Dynamic Variables

CSS variables can be read and written with JavaScript, enabling runtime theming, user preferences, and interactive effects:

// Read a variable
const primary = getComputedStyle(document.documentElement)
  .getPropertyValue('--primary').trim();

// Write a variable
document.documentElement.style.setProperty('--primary', '#e74c3c');

// Live dark mode toggle
function toggleDark() {
  const root = document.documentElement;
  const isDark = root.style.getPropertyValue('--bg') === '#1a202c';

  root.style.setProperty('--bg', isDark ? '#ffffff' : '#1a202c');
  root.style.setProperty('--text', isDark ? '#1a202c' : '#e2e8f0');
}

Why this matters: You can save user preferences (dark mode, accent color) to localStorage and restore them on next visit. The theme persists across sessions.


Complete Variable System

:root {
  /* Colors */
  --primary: #3498db;
  --primary-dark: #2980b9;
  --danger: #e74c3c;
  --success: #27ae60;
  --warning: #f39c12;
  --bg: #ffffff;
  --bg-muted: #f8f9fa;
  --text: #1a202c;
  --text-muted: #718096;

  /* Spacing */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 48px;

  /* Typography */
  --font-family: system-ui, sans-serif;
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-lg: 1.25rem;

  /* Layout */
  --max-width: 1200px;
  --radius: 8px;
  --shadow: 0 2px 8px rgba(0, 0, 0, 0.08);

  /* Transitions */
  --transition-fast: 0.15s ease;
  --transition-base: 0.3s ease;
}

Common Variable Mistakes

1. Confusing CSS Variables with Preprocessor Variables

/* ❌ Wrong: Sass/LESS syntax, not valid CSS */
$primary: #3498db;

/* ✅ Correct: CSS custom properties */
--primary: #3498db;

Sass variables ($var) are compiled away. CSS variables (--var) are live in the browser and can be changed at runtime.

2. Forgetting the var() Function

/* ❌ Wrong: --primary is not a valid value */
.button { background: --primary; }

/* ✅ Correct: use var() */
.button { background: var(--primary); }

3. Assuming Variables Work in Media Query Conditions

/* ❌ Wrong: can't use var() in a media query condition */
@media (min-width: var(--breakpoint)) { ... }

/* ✅ Correct: variables in values, not conditions */
@media (min-width: 768px) {
  :root { --columns: 3; }
}

4. Not Providing Fallbacks

/* ❌ Risky: if --btn-bg is undefined, background becomes initial (transparent) */
.btn { background: var(--btn-bg); }

/* ✅ Safe: fallback ensures something shows */
.btn { background: var(--btn-bg, #3498db); }

5. Over-scoping Variables

/* ❌ Variables on a deep child are useless elsewhere */
.card .footer .inner {
  --color: red;
}

/* ✅ Declare at the right level for the scope you need */
.card {
  --color: red;  /* Available to .card and all children */
}

Try It Yourself

Dark mode demo with variables:

▶ Try It Yourself Edit the code and click Run

Common Mistakes Beginners Make

1. Skipping the Fundamentals

Many beginners jump straight to advanced topics without mastering the basics. Take time to understand the core concepts before moving on.

2. Not Practicing Enough

Reading tutorials without writing code leads to shallow understanding. Code along with every example and experiment on your own.

3. Ignoring Error Messages

Error messages tell you exactly what went wrong. Read them carefully — they usually point to the line and type of issue.

4. Copy-Pasting Without Understanding

It’s tempting to copy code from tutorials, but typing it yourself and understanding each line builds real skill.

5. Giving Up Too Early

Every developer hits frustrating bugs. Take breaks, ask for help, and remember that struggling is part of learning.

Practice Questions

Q1: How do you declare a CSS variable and how do you access it?

Declare with --name: value; (e.g., --primary: blue;). Access with var(--name) (e.g., color: var(--primary);).

Q2: What scope do variables declared in :root have?

Global scope — they’re available to all elements on the page. Like global variables in programming.

Q3: How does scoping work with CSS variables?

Variables cascade and inherit. A child element can declare its own variable value, which overrides the parent’s value for that element and its descendants only.

Q4: How do you provide a fallback value in var()?

var(--name, fallback-value) — if --name is not defined, fallback-value is used instead.

Q5: How do you change a CSS variable with JavaScript?

document.documentElement.style.setProperty('--name', 'value') — this changes it inline, which has the highest specificity.

Challenge

Create a themeable component library using CSS variables:

  • Button, Card, Badge, Alert components
  • All colors, spacing, radii driven by variables
  • A dark theme class that changes everything
  • A “Customize” form that lets the user pick the primary color with an <input type="color">

FAQ

{< faq >}

What is Css Variables?
Css Variables refers to the core concepts and practices used to build and manage modern web applications. Understanding it is essential for web developers.
Do I need prior experience to learn Css Variables?
Basic familiarity with web development concepts helps, but Css Variables can be learned step by step even as a beginner.
How long does it take to learn Css Variables?
With consistent practice, you can grasp the fundamentals in a few days to a week. Mastery takes ongoing practice and real-world projects.
Where can I use Css Variables in real projects?
Css Variables is used in a wide range of applications — from simple websites to complex enterprise systems, depending on the specific tools and technologies involved.
What are common tools used with Css Variables?
The specific tools depend on the technology stack, but version control (Git), package managers, and testing frameworks are commonly used alongside most development topics.

{< /faq >}

FAQ

What is Variables in CSS?
: Variables refers to the CSS properties and techniques used to control how elements are displayed on a webpage. Mastering it helps you build better, more responsive layouts.
Do I need to memorize all CSS properties?
: No. Focus on understanding the core concepts and use reference docs when needed. Practice is more important than memorization.
How do I debug Variables issues?
: Use browser DevTools (F12) to inspect elements, check computed styles, and experiment with values in real time.
Is Variables the same across all browsers?
: Most modern browsers support CSS standards consistently, but always test across browsers for edge cases.
What’s the best way to practice Variables?
: Build small projects and experiment with different values. Use online playgrounds like CodePen or JSFiddle for quick testing.

What’s Next?

Now learn flexbox and grid:

What’s Next

Congratulations on completing this Css Variables tutorial! Here’s where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro