Core concepts
Adding custom styles
Extend Zazz without modifying core files using token overrides, custom cascade layers, and unlayered CSS.
Extend Zazz by loading custom styles after index.css:
<link rel="stylesheet" href="./zazz/index.css" /> <link rel="stylesheet" href="./your-styles.css" />1. Token overrides
Most customizations require updating variables rather than writing new rules:
/* your-styles.css */
:root {
--primary: oklch(0.6 0.2 145); /* global brand override */
--ui-button-radius: var(--radius-full); /* component default override */
}<!-- instance override -->
<div class="bg-card text-card-foreground rounded-md" style="--card: var(--muted)">...</div>Token overrides preserve theme switching and layer relationships.
2. Custom utility classes
Add custom utilities inside @layer zazz.utilities. Wrap selectors in :where() to maintain zero specificity:
@layer zazz.utilities {
:where(.text-gradient) {
background: linear-gradient(90deg, var(--primary), var(--secondary));
background-clip: text;
color: transparent;
}
}3. Custom components
Author new components inside @layer zazz.components using design tokens:
@layer zazz.components {
:where(.callout) {
--callout-background: var(--muted);
background: var(--callout-background);
border-inline-start: var(--step-1) solid var(--primary);
padding: var(--gap-md);
border-radius: var(--radius-md);
}
}Utilities will override component properties as expected.
4. Unlayered CSS
Rules written outside of any @layer beat all layered rules in Zazz:
.ui-button {
border-radius: 0;
}Use unlayered CSS only when intentionally bypassing the cascade layer order.
Hierarchy of customization
- Token overrides: Best for colors, spacing, radius, and sizing.
- Layered rules: Best for reusable utilities and custom components.
- Unlayered rules: For absolute overrides across the system.