Custom Properties & Fallbacks

Cascading variables that inherit, theme, and animate β€” plus the two-argument var() fallback and @property.

Custom properties (CSS variables) are not like Sass variables. They're live: they cascade, they inherit, you can read and change them at runtime, and unlike preprocessor variables they exist in the browser.

Define, use, fall back

:root {
  --brand: #2965f1;
  --space: 1rem;
}
.btn {
  background: var(--brand);
  /* second argument is used if --gap is undefined */
  gap: var(--gap, 0.5rem);
}

They cascade — that's the whole point

Set --brand on :root for a global default, then override it on a single component or a [data-theme="dark"] block. Everything downstream that reads var(--brand) updates for free. This is why theming and dark mode became a five-line job.

Registered properties with @property

A plain custom property is always treated as a string, so you can't animate it. Register it with @property to give it a type, and suddenly gradients and angles become animatable:

@property --angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

Example

Try it yourself
Loading editor…
Press Run to see the result.

When to use it

  • A developer defines brand colors as --color-primary and --color-secondary in :root so changing one variable updates the entire site's theme.
  • A designer toggles a [data-theme='dark'] attribute on the body element, which overrides :root custom properties to instantly switch every component's colors.
  • A developer uses var(--spacing-md, 16px) with a fallback value so components remain styled even in older environments that partially support custom properties.

More examples

Design token system with :root

Centralises design tokens as custom properties in :root so a single change propagates through every component.

Example Β· css
:root {
  --color-primary:   #2965f1;
  --color-danger:    #c0392b;
  --color-bg:        #fff;
  --color-text:      #1a1a2e;
  --spacing-sm:      8px;
  --spacing-md:      16px;
  --spacing-lg:      32px;
  --radius-card:     8px;
}

Dark theme via property override

Overrides custom properties on the data-theme attribute so toggling the attribute switches the entire theme instantly.

Example Β· css
:root {
  --bg: #fff;
  --text: #1a1a2e;
}
[data-theme='dark'] {
  --bg: #1a1a2e;
  --text: #f0f0f0;
}
body {
  background-color: var(--bg);
  color: var(--text);
}

var() with fallback value

Uses the two-argument var() form to supply fallback values, including a chained custom property as the fallback.

Example Β· css
.card {
  /* Uses --card-padding if set, falls back to 20px */
  padding: var(--card-padding, 20px);
  border-radius: var(--radius-card, 8px);
  background: var(--card-bg, var(--color-bg, #fff));
}

Discussion

  • Be the first to comment on this lesson.
Custom Properties & Fallbacks β€” CSS | SoundsCode