Advanced CSS · 2 min read
Custom Properties and Theming
CSS variables, inheritance and the cascade, design tokens, dark mode, and changing variables from JavaScript.
Custom properties (CSS variables) are properties you invent, prefixed with --. Unlike preprocessor variables, they are live: they inherit through the DOM, react to media queries and can be changed at runtime by JavaScript. This site's whole retro theme is a set of them.
css
:root {
--color-bg: #fff7e6;
--color-ink: #1a1530;
--color-accent: #ff3fa4;
--space: 8px;
}
.button {
background: var(--color-accent);
padding: calc(var(--space) * 1.5) calc(var(--space) * 3);
}Fallbacks and scope
css
color: var(--brand, hotpink); /* fallback if --brand is not defined */
.card { --pad: 24px; } /* scoped: only .card and its children see this value */
.card.compact { --pad: 12px; } /* override per variant */Design tokens: two layers
- Primitive tokens describe raw values:
--pink-500: #ff3fa4. - Semantic tokens describe purpose:
--accent: var(--pink-500).
Components only use semantic tokens. A theme is then just a different mapping.
<div class="controls">
<button data-theme="light">Light</button>
<button data-theme="dark">Dark</button>
<button data-theme="system">System</button>
<label>Accent hue <input id="hue" type="range" min="0" max="360" value="328"></label>
</div>
<article class="card">
<h2>NEAR Smart Contracts</h2>
<p>6 lessons · Rust · Intermediate</p>
<button class="primary">Start course</button>
</article>Edit this example in the Playground.
Moving the slider changes one variable; every component that uses --accent updates instantly.
Reading and writing from JavaScript
js
const root = document.documentElement;
getComputedStyle(root).getPropertyValue("--hue"); // " 328"
root.style.setProperty("--hue", "190");Summary
Define primitive and semantic tokens on :root, override them per theme or per component, honour prefers-color-scheme, and update variables from JavaScript for live theming.
Saved in this browser.