Overrides
How to override, tweak, and extend Vanilla Breeze without fighting the framework. The cascade layer architecture means your CSS always wins — no !important needed.
The Cascade Contract
Vanilla Breeze ships all framework CSS inside @layer blocks:
This single architectural decision makes everything else on this page work. Any CSS you write outside a layer — a plain class, an ID rule, anything unlayered — beats all layered CSS automatically.
This is the guarantee. The four levels below all build on it.
Level 1: Named Theme Override
Switch to a different theme for any section of the page by setting data-theme on an element. All descendants inherit the new theme’s tokens — colour, type, spacing, shape — automatically.
Each [data-theme] block redefines CSS custom properties at that element. Because custom properties inherit down the DOM, every child picks up the new values. Nesting works to any depth — the nearest ancestor data-theme always wins.
Notice how the same card markup produces three distinct results: default tokens, Swiss (red, Helvetica, flat), and Cyber (cyan, monospace, dark). The nested example shows Swiss → Cyber → Swiss, each layer inheriting correctly.
Level 2: Token Tweaks
Stay in a theme but adjust specific token values for a section or element. This is the most surgical option — you keep all the theme’s decisions except the ones you override.
Set custom properties on any element. Everything inside that element consumes the adjusted values. Font, spacing, and all other tokens remain untouched.
The first card shows standard Swiss. The second swaps --color-primary to purple — only the accent changes. The third overrides primary colour, border radius, and shadow all at once, but the typography and structure remain Swiss.
Level 3: Plain CSS Overrides
Write CSS. That’s it. Because the framework uses @layer, your rules win automatically. This handles cases where token tweaks aren’t enough — you want to change a specific property on a specific element, add a behaviour the theme doesn’t model, or just write your own component.
You can still use framework tokens inside your own rules. The token values respond to whatever theme is active at that element’s position in the DOM. Your rules add to the system rather than fighting it.
The left column shows Swiss defaults. The right column shows identical markup with unlayered classes applied: purple rounded card, italic pull-quote, pill-shaped button. No !important anywhere — the unlayered rules win by the cascade spec.
Level 4: Theme-Aware Utilities
Vanilla Breeze ships a @layer utilities with token-connected single-purpose classes. Unlike Tailwind utilities that bake in values at build time, VB utilities reference tokens. They respond to the active theme.
The same .bg-primary class produces Swiss red in one context and Cyber cyan in another. This is the key difference from static utility frameworks — your utilities inherit meaning from the theme.
Overriding a Utility
Utilities are inside @layer utilities. Your unlayered CSS overrides them the same way it overrides any framework style:
Combining All Four Levels
All four levels compose cleanly on the same page. This demo shows a realistic magazine-style layout that uses every level together:
- Level 1: Swiss defaults in the header; Cyber theme switch on the CTA panel
- Level 2: Muted
--color-primaryand wider leading in the editorial section - Level 3: Custom
.pull-quoteand.author-bylinecomponents (unlayered CSS) - Level 4: Utility classes (
.font-bold,.text-muted,.text-sm) on the byline
No conflicts. No specificity wars. Each level operates in its own lane because the cascade layer architecture keeps the framework out of your way.
What Not to Do
Do not use !important
It is never needed. If your rule isn’t winning, check that it is unlayered (not inside @layer). Unlayered CSS always wins.
Do not write overrides inside framework layer names
If you declare @layer components in your own stylesheet, rules in it compete with framework component rules by source order — not a reliable override path.
Do not hardcode values when a token exists
If the framework has --color-primary, use it. Hardcoding breaks theme inheritance.
Decision Guide
When you need to deviate from defaults, pick the right level:
| Situation | Approach |
|---|---|
| Entire section needs a different visual identity | data-theme attribute on the section |
| Same theme but the accent colour differs here | Token override: --color-primary: ... |
| A specific component behaviour needs to change | Unlayered modifier class |
| One-off layout or component not in the framework | Unlayered CSS class with your own rules |
| Repeated one-liner visual adjustment | Utility class from @layer utilities |
You think you need !important |
Something is wrong — check layer architecture first |
How This Differs from Tailwind
Tailwind starts with a blank slate and builds up every visual property through classes in markup. Vanilla Breeze starts with sensible defaults and steps aside when you need to change something.
| Tailwind | Vanilla Breeze |
|---|---|
| No styles by default | Styled by default |
| Add classes to build up | Override tokens or write CSS to change |
| Style lives in HTML | Style lives in CSS |
| Utility values baked at build time | Utility values connected to live tokens |
!important for overrides |
Unlayered CSS wins automatically |
| Purge/JIT build step required | No build step |
This is not anti-utility. It’s proportional. Most elements on a page should look like the theme. Classes are for exceptions, not construction.
Next Steps
Themes
Browse available themes and learn the token API.
Principles
The philosophy behind the framework.
Tokens
The full list of design tokens you can override.
Architecture Decisions
Why each structural choice was made.