# How Hallmark's Theme System Works: CSS Design Tokens and Dynamic Theme Switching

> Discover how Hallmark's theme system works using CSS design tokens and the data-theme attribute for dynamic, instant theme switching. Learn more about this innovative approach.

- Repository: [Hassan El Mghari/hallmark](https://github.com/Nutlope/hallmark)
- Tags: internals
- Published: 2026-08-16

---

**Hallmark uses a CSS-based design token system where themes override a root token set via the `data-theme` HTML attribute, enabling instant visual switches by changing CSS custom properties.**

Hallmark's theme system is built on **design tokens**—named variables for colors, typography, spacing, and motion—that cascade through the entire stylesheet. By scoping token overrides to attribute selectors like `[data-theme="cobalt"]`, the system enables multiple visual families (Lumen, Hum, Cobalt, Garden) within a single codebase. This architecture separates visual design from component implementation, making themes independently maintainable and instantly switchable at runtime.

## Core Architecture: Tokens, Overrides, and Attributes

The theme system operates in four layers that work together to deliver consistent, switchable styling.

### 1. Base Token Definitions in `:root`

Hallmark defines **fallback tokens** in the `:root` selector within [`site/css/tokens.css`](https://github.com/Nutlope/hallmark/blob/main/site/css/tokens.css). These establish the default design language when no specific theme is active.

```css
/* Base tokens (fallback) from site/css/tokens.css */
:root {
  --color-paper:          oklch(96% 0.018 80);
  --font-display:         "Fraunces", "Tiempos", ui-serif, Georgia, serif;
  --radius-card:          0;
  /* ... additional tokens */
}

```

Using **OKLCH color space** for perceptual uniformity ensures that color adjustments maintain consistent perceived lightness regardless of hue—critical for accessible, harmonious palettes.

### 2. Theme-Specific Overrides via `[data-theme]` Selectors

Each theme overrides base tokens using attribute selectors targeting the `<html>` element. When `data-theme="hum"` is set, the browser applies only the overrides defined in that scope.

```css
/* Theme overrides for "hum" theme in site/css/tokens.css */
[data-theme="hum"] {
  --color-paper:          oklch(97% 0.012 95);   /* cream paper */
  --color-accent:         oklch(86% 0.18 95);    /* pear-yellow primary */
  --color-accent-2:       oklch(66% 0.18 235);   /* sky-cyan secondary */
  --font-display:         "Plus Jakarta Sans", "Geist", "Inter", ui-sans-serif, system-ui, sans-serif;
  --radius-card:          20px;                  /* rounded corners */
  /* ... theme-specific overrides */
}

```

The browser's **cascading inheritance** automatically propagates these values to any component using `var()` references—no JavaScript re-render required.

### 3. Theme Activation via HTML Attribute

Themes are activated by setting the `data-theme` attribute on the `<html>` element:

```html
<!-- Activate the "hum" theme -->
<html data-theme="hum">
  <!-- All components inherit hum's token values -->
</html>

```

This **declarative approach** means themes apply immediately on page load, preventing flash-of-unstyled-content and supporting server-side rendering.

### 4. Runtime Theme Switching with JavaScript

Hallmark supports dynamic theme changes without page reloads by manipulating the `dataset` property:

```javascript
// Switch theme at runtime from site logic
function setTheme(name, drop = null) {
  document.documentElement.dataset.theme = name;
  if (drop) document.documentElement.dataset.drop = drop;
}

// Activate "cobalt" theme with "day" drop variant
setTheme('cobalt', 'day');

```

The second parameter enables **theme drops**—sub-variants like night/day modes within a single theme family. The Lumen theme documented in [`skills/hallmark/references/themes/lumen.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/themes/lumen.md) uses this for its night/day switching.

## Design Token Pillars

Hallmark's tokens organize into three structural pillars that every theme must define:

| Pillar | Controls | Example Tokens |
|--------|----------|---------------|
| **Palette** | Paper, ink, accent, rule colors (OKLCH-based) | `--color-paper`, `--color-accent`, `--color-accent-ink` |
| **Typography** | Font families, weights, optical sizing | `--font-display`, `--font-body`, `--display-weight` |
| **Shape & Motion** | Radius, shadows, spacing, easing, duration | `--radius-card`, `--rule-card`, `--dur-short`, `--space-3xl` |

Components reference tokens exclusively—never hardcoding values. This **token-boundary enforcement** prevents visual drift:

```css
/* Component using tokens—automatically follows active theme */
.article {
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-body);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

```

## Theme Families and Documentation

Hallmark maintains detailed documentation for each visual family in `skills/hallmark/references/themes/`:

- **[`hum.md`](https://github.com/Nutlope/hallmark/blob/main/hum.md)** — The Hum theme's cream paper, pear-yellow accents, and rounded geometry
- **[`cobalt.md`](https://github.com/Nutlope/hallmark/blob/main/cobalt.md)** — Cobalt's blue-forward palette with day/night drop handling
- **[`lumen.md`](https://github.com/Nutlope/hallmark/blob/main/lumen.md)** — Lumen's high-contrast system including special tokens for drop variants

These narrative files describe **anti-patterns** and intended usage, complementing the technical definitions in [`site/css/tokens.css`](https://github.com/Nutlope/hallmark/blob/main/site/css/tokens.css).

## Enforcement and Consistency

The [`skills/hallmark/references/slop-test.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/slop-test.md) file defines **token usage rules** that prevent regressions. This enforcement layer ensures:

- No hardcoded values in component styles
- No token improvisation outside defined sets
- Consistent motion curves and spacing scales across themes

## Summary

- **Hallmark's theme system centers on CSS custom properties** scoped via the `data-theme` HTML attribute, defined in [`site/css/tokens.css`](https://github.com/Nutlope/hallmark/blob/main/site/css/tokens.css)
- **Base tokens in `:root`** provide fallbacks; theme overrides in `[data-theme="..."]` selectors apply specific visual families
- **Three token pillars**—palette, typography, shape/motion—ensure complete theme coverage without gaps
- **Runtime switching** via `document.documentElement.dataset.theme` enables instant visual changes without page reloads
- **Theme drops** (`data-drop` attribute) support sub-variants like Lumen's night/day modes
- **Documentation and enforcement rules** in `skills/hallmark/references/` maintain system integrity across contributions

## Frequently Asked Questions

### How do I add a new theme to Hallmark?

Create a new `[data-theme="mytheme"]` selector block in [`site/css/tokens.css`](https://github.com/Nutlope/hallmark/blob/main/site/css/tokens.css) that overrides all required base tokens—palette, typography, and shape/motion values. Document the theme's design rationale in [`skills/hallmark/references/themes/mytheme.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/themes/mytheme.md), following the structure of existing theme files like [`hum.md`](https://github.com/Nutlope/hallmark/blob/main/hum.md) or [`cobalt.md`](https://github.com/Nutlope/hallmark/blob/main/cobalt.md). Ensure your theme passes the token usage rules defined in [`slop-test.md`](https://github.com/Nutlope/hallmark/blob/main/slop-test.md).

### Why does Hallmark use OKLCH for colors instead of HSL or hex?

OKLCH provides **perceptual uniformity**—a given lightness value appears equally bright regardless of hue. This makes accessible color adjustments predictable and ensures that theme variations maintain consistent contrast ratios. The [`tokens.css`](https://github.com/Nutlope/hallmark/blob/main/tokens.css) file specifies all palette values in OKLCH syntax like `oklch(97% 0.012 95)`.

### What's the difference between a theme and a drop?

A **theme** is a complete visual family (Hum, Cobalt, Garden) with full token overrides. A **drop** is a sub-variant within a theme—like Lumen's "day" or "night" modes—that changes a subset of tokens (typically palette values) while preserving typography and motion. Drops activate via the separate `data-drop` attribute, allowing orthogonal combinations like `data-theme="lumen" data-drop="night"`.

### How does Hallmark prevent components from breaking theme consistency?

The theme system enforces **token-boundary discipline**: components must use `var()` references exclusively, never literal values. The [`slop-test.md`](https://github.com/Nutlope/hallmark/blob/main/slop-test.md) reference file codifies these rules, and the centralized [`tokens.css`](https://github.com/Nutlope/hallmark/blob/main/tokens.css) architecture makes token improvisation structurally obvious during code review. Any hardcoded color, font, or spacing value violates the system and can be caught statically.