Home / Snippets / Typography /

Syntax highlight theme (CSS-only)

Token-coloured code blocks with zero JavaScript — just span classes and oklch() colors.

/* Card component styles */
.card {
  background: oklch(0.19 0.02 260);
  border-radius: 0.75rem;
  padding: 1.5rem;
  color: var(--text);
}

.card:hover {
  box-shadow: 0 4px 16px oklch(0 0 0 / 0.3);
}

@media (prefers-color-scheme: dark) {
  .card { border: 1px solid oklch(0.28 0.02 260); }
}
Widely Supported
typographycolorno-js

Quick implementation

.code-theme {
  background: oklch(0.15 0.02 260);
  border-radius: 0.75rem;
  padding: 1.25rem 1.5rem;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.85rem;
  line-height: 1.7;
  overflow-x: auto;
  border: 1px solid oklch(0.26 0.02 260);
}

/* Token classes */
.code-theme .kw   { color: oklch(0.70 0.18 300); } /* keywords — purple */
.code-theme .str  { color: oklch(0.78 0.14 145); } /* strings  — green  */
.code-theme .cmt  { color: oklch(0.55 0.03 260); font-style: italic; } /* comments — dim */
.code-theme .prop { color: oklch(0.80 0.14 60);  } /* properties — amber */
.code-theme .val  { color: oklch(0.74 0.16 195); } /* values — teal */
.code-theme .sel  { color: oklch(0.85 0.10 220); } /* selectors — sky */

Prompt this to your LLM

Includes role, constraints, token categories, and dark-theme colour guidance.

You are a senior frontend engineer building a CSS-only syntax highlight theme.

Goal: A dark syntax theme using span classes for token coloring — no JavaScript, no highlight library.

Technical constraints:
- Use oklch() for all colors — no hex, no rgba().
- Dark background: oklch(0.15 0.02 260) (near-black with a cool hue).
- Token classes: .kw (keywords), .str (strings), .cmt (comments), .prop (properties), .val (values), .sel (selectors).
- Colors must have sufficient contrast against the dark background (WCAG AA minimum).
- Apply font-style: italic to comments — convention users expect.
- Use JetBrains Mono or a monospace stack as font-family.

Token colour guidance:
- Keywords (.kw): purple hue, oklch hue ~300.
- Strings (.str): green hue, oklch hue ~145.
- Comments (.cmt): dim/muted, low chroma, hue ~260.
- Properties (.prop): amber/gold, oklch hue ~60.
- Values (.val): teal/cyan, oklch hue ~195.
- Selectors (.sel): light blue, oklch hue ~220.

Framework variants (pick one):
A) Plain HTML — wrap tokens in <span class="kw"> etc. inside a <pre class="code-theme">.
B) React component — accept a pre-tokenised array of {type, text} objects and render spans.

Edge cases to handle:
- Long lines must scroll horizontally (overflow-x: auto on the pre).
- Theme must look correct on dark backgrounds only (this is a dark-mode-first project).
- Nested tokens (e.g. a keyword inside a string) should not break — use specificity carefully.

Return CSS only.

Why this matters in 2026

Syntax highlighting is no longer exclusive to heavy libraries like highlight.js or Prism. When you control the HTML output — in a CMS, static site generator, or server-rendered template — you can inject lightweight span classes and let CSS do the colouring. The result is instant rendering with zero JavaScript parse time and a theme that inherits your design tokens.

The logic

Each token type gets a dedicated class: .kw for keywords, .str for strings, .cmt for comments, .prop for properties, and .val for values. The oklch() color space makes hue selection perceptually consistent — purple keywords at hue 300, green strings at 145, amber properties at 60, and teal values at 195 all carry similar visual weight at the same lightness and chroma. Only the comments are dim, with low chroma, to recede visually.

Accessibility & performance

Each token color must achieve at least 4.5:1 contrast against the oklch(0.15 0.02 260) background. Because oklch() decouples lightness from hue, it is easy to raise or lower lightness uniformly across all tokens without shifting their hue relationships. Italic comments follow a decades-old convention that reduces their visual prominence while preserving readability. The entire theme adds fewer than 20 CSS declarations — no runtime cost, no layout shift.