Theming

Override the variables

Every colour, size and font is a CSS variable (the full list is on Colors). Tsunami declares them in the lowest cascade layer, so a plain rule of yours wins without !important or a more specific selector. Load your CSS after tsunami.min.css and set the variables on :root.

A link New

--accent is the colour of links, the primary button and the focus ring. --on-accent is the text on top of it.

Light and dark need their own values

A rule on :root applies in both themes, so a colour that works on a light page is usually too dark on a dark one. Set the dark value for the two places Tsunami turns dark on: an explicit data-theme="dark", and the system setting when no theme is chosen.

The short way is light-dark(), used in the first example: it takes the light value, then the dark one, and follows the theme. The long way below does the same with two selectors.

:root {
  --accent: #9a3f8f;
}

:root[data-theme="dark"] {
  --accent: #d58bcc;
  --on-accent: #1a0d18;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --accent: #d58bcc;
    --on-accent: #1a0d18;
  }
}

Keep the text readable

Check each pair you change. WCAG asks for a contrast ratio of at least 4.5 to 1 for text.

  • --accent on --bg and on --surface, because it colours links.
  • --on-accent on --accent, the label of the primary button.
  • --muted on --bg and on --subtle, for hints.
  • Each status pair: --ok-fg on --ok-bg, and the same for danger, warning, info and neutral.

In this repository, bun run check:a11y reports a pair that fails, in light and dark, on every docs page.

Only part of a page

Variables follow the cascade, so set them on any element to theme just its content: a card, a sidebar or an embedded widget. The preview above does exactly that.

Type, shape and spacing

Variables Controls
--font-sans, --font-mono The text and code typefaces.
--text-sm, --text-base, --text-lg, --text-xl, --leading Font sizes and line height.
--radius-sm, --radius-md, --radius-lg Corner radius: set all three to 0 for a square look.
--space-1 to --space-6 The spacing scale that gaps and padding use.

Do not add your own variables to Tsunami's set, and do not restyle a component with its internal selectors: change the variable, and every component follows.