Skip to content
Sveltier
Mode
Theming

Custom themes

defineTheme() builds a complete theme from the parts you change. Everything else comes from a base theme, and readable on- colours are computed for you.

Define a theme

Pass only what differs, and the theme you extend as the second argument. Missing colours and contract variables come from it.

brand.ts
import { defineTheme } from 'sveltier';
import { monolithLight } from 'sveltier/themes/monolith';

// Extends Monolith light; everything you leave out comes from it.
export const brand = defineTheme({
  colors: {
    primary: 'oklch(0.52 0.16 255)',   // on-primary is computed for you
    brand: 'oklch(0.62 0.17 35)'        // custom colour: --sv-color-brand, --sv-on-brand
  },
  variables: {
    'radius-md': '13px',
    'font-display': "'Fraunces Variable', Georgia, serif"
  }
}, monolithLight);
  • Every overridden or added colour gets an on- colour: a deep ink or a near-white tinted with its hue, whichever contrasts more. Pass 'on-primary' yourself to override it.
  • Custom colours (like brand above) become --sv-color-brand and --sv-on-brand.
  • Extra variables are emitted as --sv-<name> too.

Extend a theme pack

Any pack, or any theme you defined, can be the base:

Aurora, teal
import { defineTheme } from 'sveltier';
import { aurora, auroraDark } from 'sveltier/themes/aurora';

// Aurora with a teal primary; everything else is Aurora's.
const teal = defineTheme({ colors: { primary: 'oklch(0.78 0.11 190)' } }, auroraDark);

const themes = { ...aurora, 'aurora-teal': teal };

Check contrast

Built-in themes pass a WCAG contrast suite. Your colours are yours to check; the same helpers are exported:

contrast()
import { contrast, parseOklch } from 'sveltier';

const ratio = contrast(parseOklch(theme.colors.text)!, parseOklch(theme.colors.background)!);
// ≥ 4.5 for body text (WCAG 1.4.3)

Override with CSS

For one-off changes you do not need a theme at all. Library CSS lives in cascade layers, so plain CSS wins:

app.css
/* Your styles are unlayered, so they win over every Sveltier layer
   without !important. */
.sv-theme-provider--background {
  padding: var(--sv-space-34);
}

See the theme contract for every variable a theme can set, and the defineTheme API.