Riadh Chelbi
← All posts

Design Tokens in Pure CSS

Date —
July 1, 2026
Tags —
CSS, Design Systems

Most Tailwind projects define colors in tailwind.config.js. This site does it differently — six CSS custom properties on :root define every color, and Tailwind reads from them at runtime via @theme inline.

This means changing the entire color scheme requires editing five hex values. Dark mode swaps those five values by toggling a .dark class on <html>. No build step, no recompilation, no flash.

The tokens

:root {
--paper: #f7f6f3; /* page background */
--ink: #15161b; /* primary text */
--ink-soft: #5b5d66; /* secondary text */
--signal: #3d3dff; /* the one accent color */
--line: #e4e2dc; /* borders, rules */
--surface: #efeeea; /* cards, raised panels */
}
.dark {
--paper: #101114;
--ink: #f2f1ed;
--ink-soft: #9a9ca6;
--signal: #7b7bff;
--line: #26272c;
--surface: #1a1b20;
}

Every component uses Tailwind utilities like bg-paper, text-ink, text-signal that resolve to these variables. The typography plugin is also re-themed to use the same tokens instead of its default gray scale.

@theme inline {
--color-paper: var(--paper);
--color-ink: var(--ink);
--color-ink-soft: var(--ink-soft);
--color-signal: var(--signal);
--color-line: var(--line);
--color-surface: var(--surface);
}

The tradeoff is that you lose some of Tailwind’s color palette granularity. For a site this size, that’s not a real loss — and the consistency is worth it.