Phase 5 · Modern CSS & EffectsModule 21~28 min read

Custom Properties & CSS Functions

Write DRY, themeable, fluid CSS with variables and functions like calc() and clamp().

What you'll learn

Repeating the same colour or spacing value across a stylesheet is fragile — change one and you have to find them all. Custom properties (CSS variables) fix that, and functions like calc() and clamp() let CSS compute values for truly fluid, themeable designs.

By the end you'll be able to:

  • Define and use custom properties
  • Scope variables and build a theme (light/dark)
  • Do maths in CSS with calc()
  • Create fluid values with clamp(), min(), and max()

Custom properties

A custom property is a name beginning with --, holding any value. You usually declare your global ones on :root (the whole document), then read them anywhere with var(). Define your brand colour, spacing, and radius once — reuse them everywhere:

variables.css
:root {
  --brand: #6366f1;
  --space: 16px;
  --radius: 12px;
}

.button {
  background: var(--brand);
  padding: var(--space);
  border-radius: var(--radius);
}
variables.html
Live preview
A card styled entirely from custom properties.

Note

These are real, live variables — unlike a preprocessor's compile-time variables, CSS custom properties exist in the browser, inherit through the DOM, and can even be changed with JavaScript. That's what makes instant theming possible.

Scoping & theming

Custom properties inherit, so a variable set on an ancestor applies to everything inside it. This makes theming almost effortless: define your colours as variables, then override them under a selector like [data-theme="dark"]. Flip one attribute and the whole page re-themes:

theme.css
:root {
  --bg: #ffffff;
  --text: #111827;
}

[data-theme="dark"] {
  --bg: #0f172a;
  --text: #e5e7eb;
}

body {
  background: var(--bg);
  color: var(--text);
}

Key idea

This is exactly how modern dark mode works. Because every colour reads from a variable, switching the theme means changing a handful of variable values in one place — not editing hundreds of rules. Design with variables from the start and theming comes for free.

calc()

calc() performs arithmetic, and its superpower is mixing units — something otherwise impossible. calc(100% - 32px) means "full width minus 32 pixels," perfect for leaving room for a margin or a fixed sidebar. It happily combines percentages, pixels, rem, and variables.

clamp(), min() & max()

These functions make values fluid and responsive without media queries. clamp(min, preferred, max) picks the preferred value but never goes below the min or above the max — ideal for typography that scales with the screen yet stays readable:

fluid.css
.container {
  width: calc(100% - 2 * var(--space));  /* mix units & variables */
}

h1 {
  /* min 1.5rem, scales with viewport, never past 3rem */
  font-size: clamp(1.5rem, 5vw, 3rem);
}

Recap & quick check

Key takeaways

  • Custom properties (--name) hold reusable values; read them with var(--name, fallback).
  • Declare global variables on :root; they inherit through the DOM.
  • Theming is easy: define colours as variables and override them under a theme selector.
  • calc() does maths and can mix units, like calc(100% - 32px).
  • clamp(min, preferred, max) creates fluid, responsive values with no media queries.

Quick check

1. How do you define a global custom property?

2. How do you use a custom property's value?

3. What makes CSS custom properties special vs preprocessor variables?

4. What can calc() do that plain values can't?

5. What does clamp(1.5rem, 5vw, 3rem) do?

Your CSS is DRY and themeable now. Next we unlock powerful selectors and generated content with advanced selectors and pseudo-elements.