Principles
Vanilla Breeze is built on a philosophy of progressive enhancement, simplicity, and respect for the web platform. Understanding these principles helps you get the most out of the library.
The Three-Layer Architecture
Vanilla Breeze organizes web development into three distinct, optional layers. Each layer builds on the previous without requiring it.
Layer 1: HTML
Semantic markup that works everywhere. Content is accessible, indexable, and functional with no styling at all.
Required: Always
Layer 2: CSS
Design tokens, native element styling, and CSS-only custom elements. Full visual polish without any JavaScript.
Required: Optional
Layer 3: JavaScript
Web components for complex interactivity: animations, keyboard navigation, ARIA management, and dynamic behavior.
Required: Optional
How the Layers Work Together
Consider an accordion component:
| Layer | What You Get | Code |
|---|---|---|
| HTML only | Functional expand/collapse with native <details> |
<details><summary>Title</summary>Content</details> |
| HTML + CSS | Styled with proper spacing, typography, and visual hierarchy | Same HTML, Vanilla Breeze CSS loaded |
| HTML + CSS + JS | Smooth animations, keyboard navigation, exclusive mode | <accordion-wc> wrapper added |
Each layer is an enhancement, not a requirement. Your content works at every level.
Why HTML-First Matters
Many frameworks treat HTML as an afterthought or a compile target. Vanilla Breeze treats it as the foundation.
Benefits of HTML-First
Resilience
When JavaScript fails (and it will), your content remains accessible. Forms still submit. Links still navigate. Information is still readable.
Performance
HTML renders immediately. Users see content before CSS and JavaScript finish loading. No blank screens, no loading spinners for basic content.
SEO and Discoverability
Search engines can index all your content without executing JavaScript. Social media previews work correctly. Screen readers work out of the box.
Simplicity
HTML is the simplest programming language. Anyone can learn it. There's no build step, no transpilation, no framework-specific syntax to master.
Longevity
HTML from 1995 still works today. Frameworks come and go; semantic HTML persists. Your investment in learning HTML pays dividends forever.
The Web Platform is Powerful
Modern HTML provides more than many developers realize:
<details>and<summary>for accordions<dialog>for modals with built-in focus trappingpopoverattribute for popovers and dropdowns<input type="date">for date pickers<input type="color">for color pickers<progress>and<meter>for progress indicators- Form validation with
required,pattern,min,max :has(),:is(), and:where()for powerful CSS selectors
Vanilla Breeze enhances these native capabilities rather than replacing them.
Progressive Enhancement
Progressive enhancement means starting with a baseline experience that works for everyone, then adding capabilities for browsers and users that support them.
How Vanilla Breeze Implements This
CSS Custom Elements Without JavaScript
Layout elements like <layout-stack> and <layout-grid> work purely with CSS. No JavaScript registration is needed because they use CSS attribute selectors:
/* This selector works whether or not the element is registered */layout-stack { display: flex; flex-direction: column;} layout-stack[data-layout-gap="m"] { gap: var(--size-m);}
Web Components That Enhance Native Elements
JavaScript web components wrap native HTML patterns. The native pattern always works; the web component adds polish:
<!-- This works without JS, styled by CSS --><details> <summary>Click to expand</summary> <p>Content is always accessible</p></details> <!-- This adds animations and keyboard features --><accordion-wc> <details> <summary>Click to expand</summary> <p>Content with smooth animation</p> </details></accordion-wc>
Graceful Degradation Patterns
Components use the :defined pseudo-class to style differently before and after JavaScript runs:
/* Before JS registers the component */tab-set:not(:defined) { /* Show all panels stacked */} /* After JS registers the component */tab-set:defined { /* Show tab navigation */}
Zero Dependencies
Vanilla Breeze has no runtime dependencies. The CSS and JavaScript are self-contained.
Why This Matters
- Security: No supply chain vulnerabilities from transitive dependencies
- Stability: No breaking changes from upstream packages
- Size: You get exactly what you need, nothing more
- Simplicity: No package manager required for basic usage
- Longevity: Works as long as browsers support standard web APIs
How We Achieve This
Vanilla Breeze uses only:
- Standard CSS with custom properties
- Native Web Components API
- CSS
@layerfor cascade management - No polyfills required (targets modern evergreen browsers)
Development dependencies exist for building and testing, but they never ship to users.
Semantic Naming
Names should describe what something is, not how it looks.
Custom Elements
Custom elements use descriptive, hyphenated names that are self-documenting:
<!-- Layout describes what it does --><layout-stack> <!-- Stacks children vertically --><layout-cluster> <!-- Clusters items horizontally with wrapping --><layout-sidebar> <!-- Creates a sidebar layout --><layout-grid> <!-- Responsive grid layout --> <!-- Web components describe their purpose --><accordion-wc> <!-- Accordion behavior --><tab-set> <!-- Tab interface --><toast-msg> <!-- Toast notifications -->
CSS Classes
Classes describe variants or purposes, not visual properties:
<!-- Good: describes purpose --><button class="secondary">Cancel</button><button class="ghost">Learn More</button><nav class="horizontal pills">...</nav> <!-- Avoid: describes appearance --><button class="gray">Cancel</button><button class="no-background">Learn More</button>
Design Tokens
Tokens use semantic names that adapt to context:
/* Good: semantic purpose */color: var(--color-text); /* Adapts to light/dark */color: var(--color-text-muted); /* Secondary text */background: var(--color-surface); /* Main background */background: var(--color-interactive); /* Interactive elements */ /* Avoid: literal values */color: var(--gray-700);background: var(--white);
Data Attributes for Configuration
Vanilla Breeze uses data-* attributes rather than classes for component configuration and state. This creates a clear separation of concerns.
Why Data Attributes?
| Aspect | Classes | Data Attributes |
|---|---|---|
| Purpose | Styling hooks | Configuration and state |
| Values | Boolean only (present/absent) | Any string value |
| JavaScript access | classList.contains() |
dataset.property |
| Collision risk | High (common names) | Low (namespaced) |
Convention
<!-- Configuration with values --><layout-stack data-layout-gap="m" data-layout-align="center"><layout-grid data-layout-min="200px" data-layout-gap="l"><tab-set data-orientation="vertical"> <!-- State (boolean or value) --><accordion-wc single><button data-state="loading"><input data-valid="true"> <!-- Classes for variant styling only --><button class="secondary"><nav class="horizontal pills">
Design Decisions
Every architectural choice in Vanilla Breeze traces to a specific failure mode it prevents. The principles above — HTML-first, progressive enhancement, zero dependencies, semantic naming, data attributes — are not just preferences. They are structural decisions with engineering rationale.
For the full list of decisions, the failure modes they prevent, and the trade-offs they accept, see Architecture Decisions.
Next Steps
Now that you understand the philosophy, put it into practice:
Quick Start
Get up and running in minutes.
Tutorial
Build a complete page step by step.
Accessibility
Learn how Vanilla Breeze supports accessibility.
Elements
Explore all available components.