Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
A pack is a self-contained extension that adds capabilities or a visual identity to Vanilla Breeze. Packs come in three types:
Add JS behaviors and components. No theme tokens — they work with any theme. Examples: ui, effects, prototype.
Pure visual themes — token overrides for colors, fonts, radii, easing. No JS, no new components. CSS-only.
Theme + effects + components in one coherent package. A complete visual identity. Examples: kawaii, memphis.
Vanilla Breeze core ships tokens, layouts, and web components. A pack extends this with:
Token overrides scoped to [data-theme~="name"]. Changes colors, fonts, radii, easing. Zero new CSS rules — just different values.
CSS and JS animations activated by data-effect. Add data-effect="neon" or data-effect="flipboard" to any element.
Web components with pack-specific chrome. They consume core tokens automatically — switch theme and the component adapts.
All three layers are optional. A pack can ship just a theme, just effects, just components, or any combination.
This is the key insight: pack components consume the same tokens as core. When you switch from data-theme="kawaii" to data-theme="swiss", or change the color accent via ThemeManager.setAccent('ocean'), every pack component re-renders with the new colors, fonts, and spacing. No code changes needed.
Load the full pack alongside core:
<!-- Load core Vanilla Breeze first --><link rel="stylesheet" href="/cdn/vanilla-breeze.css"><script type="module" src="/cdn/vanilla-breeze.js"></script> <!-- Load a pack (all-in-one) --><link rel="stylesheet" href="/cdn/packs/kawaii.full.css"><script type="module" src="/cdn/packs/kawaii.full.js"></script>
Load only the parts you need:
<!-- Theme tokens only (smallest payload) --><link rel="stylesheet" href="/cdn/packs/kawaii.theme.css"> <!-- Effects only (CSS data-* animations) --><link rel="stylesheet" href="/cdn/packs/kawaii.effects.css"><script type="module" src="/cdn/packs/kawaii.effects.js"></script> <!-- Components only (web components) --><script type="module" src="/cdn/packs/kawaii.components.js"></script>
Load a pack dynamically from JavaScript:
import { activateBundle } from '/cdn/vanilla-breeze.js' // Load a pack at runtime (returns a Promise)await activateBundle('kawaii') // Custom CDN pathawait activateBundle('kawaii', { basePath: '/assets/packs' })
activateBundle injects a <link> for the CSS and import()s the JS. It returns a Promise that resolves when both are loaded.
Vanilla Breeze uses CSS @layer to manage cascade priority. Pack layers sit after core layers, ensuring pack styles always win over core defaults without specificity battles:
@layer tokens, reset, native-elements, custom-elements, web-components, utils, bundle-theme, bundle-effects, bundle-components;
| Layer | Purpose | Owner |
|---|---|---|
tokens … utils |
Core Vanilla Breeze styles | Core |
bundle-theme |
Token overrides for [data-theme~="name"] |
Pack theme file |
bundle-effects |
CSS effects activated by data-effect |
Pack effects file |
bundle-components |
Web component styles (inside Shadow DOM) | Pack component files |
When no pack is loaded, the three bundle layers are empty declarations — zero cost.
A pack lives in src/packs/{name}/ and follows a strict file convention:
src/packs/kawaii/ kawaii.theme.css # Token overrides (@layer bundle-theme) kawaii.effects.css # CSS data-* effects (@layer bundle-effects) kawaii.effects.js # JS effects (VB.effect calls) kawaii.bundle.js # Pack manifest metadata fonts/ # Pack-specific assets CherryBombOne.woff2
The build pipeline produces granular and combined outputs:
dist/cdn/packs/ manifest.json # Registry of all built packs kawaii.theme.css # Theme tokens only kawaii.effects.css # Effects CSS only kawaii.effects.js # Effects JS only kawaii.full.css # Theme + effects CSS combined kawaii.full.js # Effects + components JS combined kawaii.bundle.js # Pack manifest kawaii/fonts/ # Copied assets
The theme file overrides core tokens inside a @layer bundle-theme block, scoped by a [data-theme~="name"] selector:
/* Pack theme tokens scope to a data-theme selector */@layer bundle-theme { [data-theme~="kawaii"] { --color-primary: oklch(72% 0.2 340); --radius-m: 999px; --font-display: 'Cherry Bomb One', cursive; --ease-out: cubic-bezier(0.34, 1.56, 0.64, 1); }}
Because it uses the ~= (word match) selector, users can combine themes: data-theme="kawaii dark".
CSS effects are data-effect attribute selectors in the bundle-effects layer. They must:
:root pollution)var(--color-primary) so they adapt to theme changesprefers-reduced-motion and [data-motion-reduced] overrides@media print resets/* Effects use data-effect~= selectors in the effects layer */@layer bundle-effects { [data-effect~="sparkle"] { --vb-sparkle-color: var(--color-primary); position: relative; overflow: hidden; } @media (prefers-reduced-motion: reduce) { [data-effect~="sparkle"]::before, [data-effect~="sparkle"]::after { animation: none; } }}
JS effects use the VB.effect() API. The effect system provides a shared MutationObserver that auto-initializes effects on dynamically added elements:
import { VB } from '/cdn/vanilla-breeze.js' VB.effect('flipboard', (el) => { // Set up split-flap animation const text = el.textContent.trim().toUpperCase() buildBoard(el, text) return { cleanup() { /* clean up timers and DOM */ }, }})
| Callback Return | Required | Description |
|---|---|---|
{ activate() } |
No | Called when the effect’s trigger fires |
{ cleanup() } |
No | Called when the element is removed or the effect is replaced |
Components use registerComponent for priority-based conflict resolution. Since customElements.define() is permanent, the registry uses first-wins semantics with priority tiebreaking:
import { registerComponent } from '/cdn/vanilla-breeze.js'import { MyWidget } from './components/my-widget/my-widget.js' registerComponent('my-widget', MyWidget, { bundle: 'my-pack', contract: 'my-widget', priority: 10,})
Every pack component documents which tokens it consumes and which it exposes. This makes the dependency chain explicit and enables tooling:
/* Components consume system tokens and expose their own */class MyWidget extends HTMLElement { static consumesTokens = ['--color-primary', '--color-surface-sunken'] static exposesTokens = ['--widget-accent', '--widget-bg']}
::part() API — expose named parts for external stylingvar(--color-primary) not oklch(70% 0.28 145)<audio> for JS-off fallbackbundle, contract, version, token arraysTry the packs in the interactive explorer, or load them individually in your projects.
Add capabilities beyond core. Work with any theme.
Theme picker and environment manager for broad theme switching UIs.
Text effects, animated images, ticker counters, and star ratings.
Placeholder content for rapid prototyping and wireframing.
User personas, stories, journey maps, empathy maps, impact/effort matrices, and story maps.
Token specimens, component samplers, and CSS patterns for documenting brand guidelines.
Standalone modules loaded separately: data-emoji, <emoji-picker>, extended emoji set.
Opt-in variable font bundles. One file per typographic role — no multi-weight loading.
Inter (sans/UI), Literata (serif/editorial), Recursive (mono/code). Variable fonts with axis-aware tokens.
Fraunces (WONK/SOFT axes), Cormorant (Garamond-lineage), Bodoni Moda (dramatic contrast). For editorial and marketing.
Nabla (COLR v1 3D depth), Honk (inflatable neon), Kablammo (comic impact). For hero sections and creative contexts.
Material Symbols Outlined variable icon font with attractor animations. Context-aware weight and optical size.
Theme + effects + components — a complete visual identity in one package.
Pastel pink/mint/lavender palette, pill shapes, bouncy motion, Cherry Bomb One display font, sparkle particles.
Bold flat colour, geometric surface patterns (stripes, dots, zigzag, squiggle, confetti), hard drop shadows, Boogaloo + Outfit + Space Mono fonts.
Interactive demo page — load and switch between all available packs live.
Try packs live in the interactive demo.
Understand the progressive enhancement philosophy.
Learn about the core token system that packs extend.