A framework where tokens do the work,
not tools
EXSA is built on one idea: CSS custom properties should drive everything — colors, spacing, components, themes. No CLI. No bundler. No config file. Just a cascade that knows when to step aside.
5 layers. Each with one job.
CSS @layer is the most underused feature in the language. EXSA builds its entire architecture on it — each layer feeds the next, and themes sit outside the cascade so they always win.
Tokens
36 CSS custom properties. Colors, spacing, typography, shadows. The single source of truth.
--color-link · --gap · --border-radius · --box-shadow
Reset
Box model, focus rings, scrollbars, RTL, reduced motion, forced-colors, skip links.
box-sizing · :focus-visible · [dir=rtl] · prefers-reduced-motion
Layout
65+ flex and grid utilities. No prefix. No breakpoint memorization. Just compose.
.flex · .grid · .container · .gap-md · .grid-auto-fit
Elements
Classless HTML styling — but only for unclassed elements. Add a class, the framework stays out of your way.
<section> gets cards · <section class="my-app"> doesn't
Components
49 plug-and-play components. Each is one CSS file. Link only what you need. All use :where() for zero specificity.
accordion · modal · toast · tabs · card · table · dropdown
Three ideas no other framework combines
Each one exists somewhere. Together, they're unique to EXSA.
Guarded Classless
Add body class="exsa" to get automatic HTML styling. But add any class to a structural element — <section class="my-layout"> — and EXSA steps aside. No fighting. No !important. You're in control.
Zero Specificity Everywhere
Every base style uses :where() for a specificity of zero. Your custom CSS — even a single class — always wins. No specificity wars. No !important arms race.
Runtime Theming via Tokens
All 49 components share the same 36 CSS custom properties. Swap one theme file — every component, every color, every shadow updates instantly. No recompile. No rebuild.
A11y Baked Into the Reset
forced-colors: active for Windows High Contrast Mode. prefers-reduced-motion disables all animations. prefers-contrast adjusts borders. Skip links. Focus rings. Not an afterthought — layer 2.
Tree-Shakeable by Design
Every component is its own CSS file. During development, link what you need. For production, the Generator bundles only your selected components into one file. No dead styles.
Zero Build Step. Forever.
No npm install. No webpack. No postcss.config.js. Just <link> tags and you're building. Works with any server that serves static files. PHP, Python, Node, nginx, Apache, Caddy — doesn't matter.
The same card. Two philosophies.
EXSA uses semantic component classes driven by tokens. Tailwind uses atomic utilities. See what happens when you change themes.
<div class="card"> <div class="card__body"> <h3 class="card__title">Hello</h3> <p class="card__text">Content.</p> </div> </div> Swap theme → one file. Done.
<div class="bg-white rounded-lg shadow-md p-6 max-w-sm border border-gray-200"> <h3 class="text-lg font-semibold text-gray-900 mb-2">Hello</h3> <p class="text-sm text-gray-600">Content.</p> </div> Swap theme → edit every class.
Layer 2 is the accessibility layer
Most frameworks treat accessibility as a plugin or a checklist. EXSA puts it in the reset — before layout, before components. It's not optional.
🖥️ Windows High Contrast Mode
@media (forced-colors: active) switches the focus ring to system colors and reveals screen-reader-only text. Works out of the box — no configuration.
🎯 Reduced Motion
prefers-reduced-motion: reduce disables all CSS animations, transitions, and smooth scrolling. The :target highlight animation is explicitly disabled.
🎨 Contrast Preferences
prefers-contrast: high boosts borders to full opacity and thickens link underlines. prefers-contrast: low softens borders — without thinning text.
⌨️ Keyboard Navigation
Skip-to-content link. Visible focus rings on :focus-visible. No outline on mouse clicks. scroll-behavior: smooth with a reduced-motion fallback.
Ready to try tokens over tools?
Browse 49 components, grab the cheatsheet, or use the Generator to build a custom bundle — no build step, no config, just the CSS you need.