CSS Cheatsheet

Variables

Use this CSS reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Defining Custom Properties

/* Scope to :root — available globally */
:root {
  --color-primary: #3b82f6;
  --color-text: #111;
  --spacing-sm: 0.5rem;
  --spacing-md: 1rem;
  --spacing-lg: 2rem;
  --font-sans: "Inter", system-ui, sans-serif;
  --radius: 0.5rem;
  --shadow: 0 1px 3px rgba(0,0,0,0.12);
}

/* Scoped to a component */
.card {
  --card-padding: 1.5rem;
  --card-bg: #fff;
  padding: var(--card-padding);
  background: var(--card-bg);
}
  • Name must start with --.
  • Names are case-sensitive: --Color and --color are different.
  • Value is everything after the colon: --x: 1rem sets value to 1rem (with leading space — usually fine).

Using var()

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

/* Fallback value */
color: var(--color-text, #333);

/* Nested fallbacks */
color: var(--color-heading, var(--color-text, #111));

/* Using in expressions */
margin: calc(var(--spacing-md) * 2);
transform: translateX(var(--offset, 0));

The fallback is only used when the variable is not defined or is the initial value — NOT when the value is invalid for the property. Invalid values cause the property to inherit or take its initial value.

Invalid Variables and OOTB Handling

:root { --bad: 20px; }
.text { color: var(--bad); }
/* --bad is set but 20px is invalid for color */
/* Result: color becomes inherit/initial — not the fallback! */

/* Safe guard: provide a fallback only when the property might not exist */
color: var(--user-color, currentColor);

Inheritance

Custom properties inherit through the DOM like regular inherited properties:

:root { --theme: light; }
.dark-section {
  --theme: dark;         /* overrides for all descendants */
  background: #111;
}
.child { /* sees --theme: dark */ }

Overriding in Context

:root { --accent: blue; }

.danger { --accent: red; }      /* overrides for descendants */
.danger .btn { background: var(--accent); } /* red */

[data-theme="dark"] { --accent: #60a5fa; }  /* dark mode */

@property — Typed Custom Properties

/* Register a typed custom property */
@property --angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

@property --progress {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

@property --color-stop {
  syntax: "<color>";
  inherits: false;
  initial-value: transparent;
}

/* Now --angle can be animated! */
@keyframes spin {
  to { --angle: 360deg; }
}

.spinner {
  animation: spin 2s linear infinite;
  background: conic-gradient(from var(--angle), red, blue);
}

syntax values: "<length>", "<number>", "<percentage>", "<length-percentage>", "<color>", "<image>", "<url>", "<integer>", "<angle>", "<time>", "<resolution>", "<transform-function>", "<custom-ident>", "*" (any, no type checking).

CSS Variable Design Token Patterns

Color Scales

:root {
  /* Raw values */
  --blue-100: #dbeafe;
  --blue-500: #3b82f6;
  --blue-900: #1e3a8a;

  /* Semantic aliases */
  --color-bg: var(--blue-100);
  --color-brand: var(--blue-500);
  --color-text: var(--blue-900);
}

Spacing Scale

:root {
  --space-1: 0.25rem;   /* 4px */
  --space-2: 0.5rem;    /* 8px */
  --space-3: 0.75rem;   /* 12px */
  --space-4: 1rem;      /* 16px */
  --space-6: 1.5rem;    /* 24px */
  --space-8: 2rem;      /* 32px */
  --space-12: 3rem;     /* 48px */
  --space-16: 4rem;     /* 64px */
}

Dark Mode with Variables

:root {
  --bg: #ffffff;
  --fg: #111111;
  --border: #e5e7eb;
}

[data-theme="dark"] {
  --bg: #111111;
  --fg: #f9fafb;
  --border: #374151;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #111111;
    --fg: #f9fafb;
    --border: #374151;
  }
}

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

Using Variables in calc(), hsl(), etc.

:root {
  --hue: 220;
  --saturation: 90%;
  --lightness: 50%;
}

.btn {
  background: hsl(var(--hue) var(--saturation) var(--lightness));
}

.btn:hover {
  background: hsl(var(--hue) var(--saturation) calc(var(--lightness) - 10%));
}
:root { --cols: 3; }
.grid {
  grid-template-columns: repeat(var(--cols), 1fr);
}
/* Override per context */
.sidebar .grid { --cols: 2; }

Setting Variables from JavaScript

// Set
document.documentElement.style.setProperty('--color-brand', '#ff0000');
document.querySelector('.card').style.setProperty('--card-padding', '2rem');

// Get
const val = getComputedStyle(document.documentElement)
  .getPropertyValue('--color-brand').trim();

// Remove (falls back to inherited or initial)
document.documentElement.style.removeProperty('--color-brand');

CSS Variables vs. Preprocessor Variables

FeatureCSS Custom PropertiesSass $var / Less @var
RuntimeYes — live in browserNo — compile time only
DOM scope / inheritanceYesNo
Readable from JSYesNo
Media query overrideYesNo
Animatable (with @property)YesNo
Fallback valuesYesNo
Browser supportAll modernRequires preprocessor

env() — Environment Variables

Built-in browser-level variables (not custom — cannot be set by author):

/* Safe area insets (iOS notch, home indicator) */
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom, 20px); /* fallback */
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);

/* Keyboard appearance height */
height: calc(100vh - env(keyboard-inset-height, 0px));

Gotchas

/* Variables cannot be property names */
--prop: color;
/* var(--prop): red; — INVALID */

/* Variables cannot be media query values (they're not resolved there) */
/* WRONG: */
:root { --bp: 768px; }
@media (min-width: var(--bp)) { ... } /* DOES NOT WORK */

/* Variables CAN be used in @supports if checking a property value */
@supports (color: var(--test-var)) { ... }

/* Empty value vs unset */
:root { --x: ; }       /* --x is set but empty */
:root { --x: initial; } /* --x is the guaranteed-invalid value */
width: var(--x, 100px); /* fallback used only when --x is unset, not empty */