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:
--Colorand--colorare different. - Value is everything after the colon:
--x: 1remsets value to1rem(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
| Feature | CSS Custom Properties | Sass $var / Less @var |
|---|---|---|
| Runtime | Yes — live in browser | No — compile time only |
| DOM scope / inheritance | Yes | No |
| Readable from JS | Yes | No |
| Media query override | Yes | No |
Animatable (with @property) | Yes | No |
| Fallback values | Yes | No |
| Browser support | All modern | Requires 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 */