CSS Custom Properties (Variables) Cheat Sheet

New

CSS custom properties: declaration, usage, fallbacks, scope, and dynamic theming patterns

Declaration & Usage

Declare a Variable

Variables are declared with -- prefix inside a selector

:root { --primary: #3b82f6; --spacing-md: 1rem; --border-radius: 0.5rem; }

Use with var()

Reference a custom property with var()

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

Fallback Values

Provide a fallback if the variable is not defined

.card { color: var(--text-color, #111111); background: var(--card-bg, var(--surface, white)); /* nested fallback: tries --card-bg, then --surface, then white */ }

Scoping

Global Scope (:root)

:root makes variables available everywhere in the document

:root { --color-brand: #6366f1; --font-sans: "Inter", sans-serif; }

Component Scope

Variables defined in a selector only apply to that element and its children

.card { --card-padding: 1.5rem; padding: var(--card-padding); } .card.compact { --card-padding: 0.75rem; /* override for compact variant */ }

Override in Selectors

Child elements can override inherited custom properties

:root { --text: #111; } .dark { --text: #fff; } .sidebar { --text: #555; } p { color: var(--text); } /* each context gets the right value */

Dynamic Updates with JavaScript

setProperty

Update a CSS variable from JavaScript

// Set on :root document.documentElement.style.setProperty("--primary", "#ef4444"); // Set on a specific element const el = document.querySelector(".card"); el.style.setProperty("--card-padding", "2rem");

getPropertyValue

Read a CSS variable value from JavaScript

const style = getComputedStyle(document.documentElement); const primary = style.getPropertyValue("--primary").trim(); console.log(primary); // "#3b82f6"

Theming Patterns

Light/Dark Theme

Use media query or class to switch themes

:root { --bg: #ffffff; --text: #111111; } @media (prefers-color-scheme: dark) { :root { --bg: #0f172a; --text: #f1f5f9; } } /* Or with a class: */ .dark { --bg: #0f172a; --text: #f1f5f9; }

Color System

Build a design token system with semantic naming

:root { /* Primitives */ --blue-500: #3b82f6; --blue-600: #2563eb; /* Semantic tokens */ --color-primary: var(--blue-500); --color-primary-hover: var(--blue-600); --color-surface: #ffffff; --color-text: #111827; }

With calc()

calc() with Variables

Use custom properties in calc() expressions

:root { --base-spacing: 0.25rem; --sidebar-width: 16rem; } .main { padding: calc(var(--base-spacing) * 4); /* 1rem */ width: calc(100% - var(--sidebar-width)); }

Media Queries with Variables

Responsive Variables

Change variable values at different breakpoints

:root { --font-size-base: 1rem; --spacing-lg: 2rem; } @media (min-width: 768px) { :root { --font-size-base: 1.125rem; --spacing-lg: 3rem; } }

Common Patterns

Theme System with Variables

Complete light/dark theme using custom properties

/* themes.css */
:root {
  --color-bg:          #ffffff;
  --color-surface:     #f8fafc;
  --color-text:        #0f172a;
  --color-text-muted:  #64748b;
  --color-primary:     #3b82f6;
  --color-primary-fg:  #ffffff;
  --color-border:      #e2e8f0;
  --shadow:            0 1px 3px rgba(0,0,0,0.1);
}

.dark {
  --color-bg:          #0f172a;
  --color-surface:     #1e293b;
  --color-text:        #f1f5f9;
  --color-text-muted:  #94a3b8;
  --color-primary:     #60a5fa;
  --color-primary-fg:  #0f172a;
  --color-border:      #334155;
  --shadow:            0 1px 3px rgba(0,0,0,0.5);
}

Component-Scoped Variables

Use local variables for component variants

/* Button with CSS variable variants */
.btn {
  --btn-bg:    var(--color-primary);
  --btn-fg:    var(--color-primary-fg);
  --btn-py:    0.5rem;
  --btn-px:    1rem;
  --btn-radius: 0.375rem;

  background:    var(--btn-bg);
  color:         var(--btn-fg);
  padding:       var(--btn-py) var(--btn-px);
  border-radius: var(--btn-radius);
}

.btn.btn-lg {
  --btn-py: 0.75rem;
  --btn-px: 1.5rem;
}

.btn.btn-danger {
  --btn-bg: #ef4444;
  --btn-fg: #ffffff;
}

JavaScript Theme Toggle

Toggle dark mode by updating a CSS variable on :root

// React theme toggle hook
function useTheme() {
  const [theme, setTheme] = useState(() => {
    return localStorage.getItem("theme") || "light";
  });

  useEffect(() => {
    const root = document.documentElement;
    if (theme === "dark") {
      root.classList.add("dark");
    } else {
      root.classList.remove("dark");
    }
    localStorage.setItem("theme", theme);
  }, [theme]);

  const toggle = () => setTheme(t => t === "light" ? "dark" : "light");
  return { theme, toggle };
}

Tips & Best Practices

Prefix component variables with the component name (--btn-bg, --card-padding) to avoid conflicts

Always provide a fallback value for variables that might not be defined: var(--color, #default)

Use CSS variables for design tokens — they are the ideal bridge between design systems and code

CSS variables are inherited — changing a variable on a parent automatically updates all children

CSS variables are live — changing them via JavaScript updates the UI instantly without a page reload