Documentation
Everything you need to build with EXSA. Start with the 5-minute quick start, then dive into the concepts that make this framework different.
Getting Started
EXSA has zero dependencies. No npm, no webpack, no build step. It works with any server that serves static files — Apache, nginx, PHP, Python, Node, Caddy, or just opening .html files directly.
1. Download or clone
# Option A: Copy the concept_d/ folder into your project
your-project/
├── style.css ← core: tokens, reset, layout, elements
├── components/ ← 49 component CSS files
├── components.js ← interactive behaviors
└── themes/ ← 17 theme files
2. Link the core
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="themes/breeze.css">
style.css) is 11.8 KB and includes tokens, reset, layout utilities, and classless element styles. The theme file overrides ~12 color tokens. You're ready to build.Your First Page
Create an index.html with body class="exsa" to enable classless element styling — HTML elements automatically get typography, spacing, and link styling without writing a single CSS rule.
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="themes/breeze.css">
</head>
<body class="exsa">
<header>
<h1>My Site</h1>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
</ul>
</nav>
</header>
<main>
<section>
<h2>Welcome</h2>
<p>This paragraph gets automatic margin and typography.</p>
<p><code>Inline code</code> gets accent background styling.</p>
<aside>This becomes a card — border, shadow, responsive padding.</aside>
</section>
</main>
<footer>
<p>© 2026</p>
</footer>
</body>
</html>
The <header> is centered and padded. The <nav> is a flex row. <aside> elements inside <section> become cards. All of this happens without a single class — it's the classless engine working.
Adding Components
Each component is a single CSS file in the components/ folder. Link only what you need.
<!-- Add these after style.css -->
<link rel="stylesheet" href="components/buttons.css">
<link rel="stylesheet" href="components/card.css">
<link rel="stylesheet" href="components/modal.css">
<link rel="stylesheet" href="components/tabs.css">
<!-- For interactive components, also include the JS -->
<script src="components.js"></script>
Then use them in your HTML:
<button class="btn btn--primary">Click Me</button>
<div class="card">
<div class="card__body">
<h3 class="card__title">Card Title</h3>
</div>
</div>
<div class="modal" id="my-modal">...</div>
exsa.bundle.css with everything you picked — no unused styles.The 5-Layer Cascade
EXSA uses CSS @layer to enforce an explicit cascade order. Each layer has one job. Layers lower in the list override layers higher — and themes sit outside all layers, so they always win.
@layer exsa.tokens, exsa.reset, exsa.layout, exsa.elements, exsa.components;
@layer, specificity determines which rule wins — a class from a component could accidentally override a token. With layers, the cascade order is explicit and predictable regardless of specificity.Layer 1: Tokens
36 CSS custom properties defined on :root. Colors (--color-link, --color-bg), spacing (--gap, --gap-sm), typography (--font-family, --line-height), shadows, border radius, hover brightness. Everything else references these.
Override any token in your own stylesheet or swap the theme file — all components update automatically.
Layer 2: Reset
Box-sizing, focus rings, scrollbar styling, RTL support, reduced motion, forced-colors mode, skip links, body defaults. Applies globally — no opt-in needed.
Layer 3: Layout
65+ utility classes for flex, grid, gap, containers, positioning, text alignment, overflow, and responsive breakpoints. Always on. No prefix.
Layer 4: Elements
Classless HTML styling — activated by body class="exsa". Styles <p>, <a>, <code>, <pre>, <nav>, <section>, <aside>, and more. Uses :where() for zero specificity.
Layer 5: Components
49 self-contained components — each is one CSS file. Link only what you need. All use :where() for zero specificity.
Tokens — The Source of Truth
Every visual decision in EXSA flows from 36 CSS custom properties. Change a token — every component, every element, every utility that references it updates instantly.
/* Key tokens you'll override most often */
--color-bg: #fff; /* page background */
--color-text: #000; /* body text */
--color-link: #118bee; /* links, primary actions, focus ring */
--color-secondary: #920de9; /* accent, visited links */
--color-bg-secondary: #e9e9e9; /* cards, stripes, borders */
--border-radius: 5px; /* all rounded corners */
--box-shadow: 2px 2px 10px; /* shadow offset + blur */
--font-family: ...; /* system font stack */
/* Spacing scale — 7 steps */
--gap-xs: 0.25rem; --gap-sm: 0.5rem; --gap-md: 0.75rem;
--gap: 1rem; --gap-lg: 1.5rem; --gap-xl: 2rem;
--gap-2xl: 3rem;
/* Semantic colors */
--color-success: #16a34a; /* green */
--color-danger: #dc2626; /* red */
--color-warning: #d97706; /* amber */
Full token reference: Cheatsheet → Tokens
tokens.json exports all 36 tokens in a structured JSON format — import into Figma (via Tokens Studio), JavaScript, or Tailwind config. Light and dark values included for every color token.Classless Elements
Add class="exsa" to <body> and semantic HTML elements get automatic styling:
<p>— 0.75rem vertical margin<a>— bold, underlined, link-colored, brightness on hover/active<code>— inline code with accent background, border-radius, padding<pre>— block code with max-width, padding, scroll overflow<hr>— 1px divider, 3rem margin<nav>— flex row, space-between, bold, 2rem bottom margin<section>— flex-wrap container for cards (unguarded sections only)<aside>— card with border, shadow, hover lift, container-responsive padding
All classless styles use :where() — specificity of zero. A single class from your own CSS always wins.
Guarded Styles
EXSA uses :not([class]) on structural container rules — <section>, <header>, <main>, <footer>. If you add any class to these elements, the framework's layout rules step aside.
<!-- Framework styles this: flex-wrap, centered cards -->
<section>
<aside>Card 1</aside>
<aside>Card 2</aside>
</section>
<!-- Framework stays out — you're in control -->
<section class="my-custom-layout">
<!-- display, flex-wrap, justify-content NOT set by EXSA -->
<!-- But <aside> cards inside STILL get styled -->
</section>
<section>, child <aside> elements still get card styling. <nav> children (<ul>, <li>) always get dropdown behavior. Only the container's layout properties are guarded.How Themes Work
A theme is a CSS file that overrides ~12 color tokens on :root. Because themes are loaded outside the @layer cascade (unlayered styles always win), theme values always override the default tokens.
/* themes/night.css — a complete theme in ~12 lines */
:root {
--color-bg: #1c1f2e;
--color-bg-secondary: #2a2d3a;
--color-text: #e2e4e9;
--color-text-secondary: #9498a4;
--color-link: #60a5fa;
--color-secondary: #c084fc;
--color-accent: #60a5fa18;
--color-secondary-accent: #c084fc18;
--color-shadow: #00000040;
--color-scrollbar: #3a3d4a;
--color-table: #60a5fa;
}
Swap themes by changing one <link> href. All 49 components, all element styles, all utilities — everything recolors instantly. No rebuild.
Creating a Custom Theme
Copy any existing theme file (start with breeze.css for light, night.css for dark) and override these tokens:
- Background pair:
--color-bg+--color-bg-secondary - Text pair:
--color-text+--color-text-secondary - Brand colors:
--color-link+--color-secondary - Accent tints:
--color-accent+--color-secondary-accent(use 8-digit hex with alpha) - Semantic colors:
--color-success,--color-danger,--color-warning(and their-hovervariants) - Chrome:
--color-scrollbar,--color-shadow,--color-table
#118bee15 means #118bee at ~8% opacity. The last two digits are hex alpha — 00 (transparent) to FF (opaque). Use this for subtle tint backgrounds.Dark Mode & System Preference
EXSA supports three approaches to dark mode:
1. System preference (built-in)
The default tokens include a @media (prefers-color-scheme: dark) block with dark defaults. If you don't load a theme file, the framework automatically switches based on OS preference.
2. Dark-first themes
Themes like night, volt, ember, abyss, shadow, ink are dark by default. They set dark tokens at :root level — no media query needed.
3. Runtime switching (JavaScript)
// Switch theme programmatically
document.getElementById('theme-stylesheet').href = 'themes/night.css';
Layout Utilities
65+ utility classes in the layout layer. Always on, no prefix, no breakpoint memorization. Full reference: Cheatsheet → Layout.
Containers
.container /* max-width: 1080px, centered, padded */
.container-sm /* max-width: 800px */
.container-full /* width: 100% */
Flex
.flex .flex-col .flex-wrap .flex-1
.justify-center .justify-between .items-center
.gap-sm .gap .gap-lg .gap-xl
Grid
.grid .grid-cols-3 .grid-auto-fit
Position & Sizing
.relative .absolute .fixed .sticky .inset-0
.w-full .h-full .overflow-hidden .overflow-auto
.text-center .text-left .text-right
Responsive Helpers
Three breakpoints. Classes activate at or below the specified width:
| Breakpoint | Width | Examples |
|---|---|---|
sm: | ≤ 575px | .sm\:flex-col .sm\:grid-cols-1 |
md: | ≥ 768px | .md\:col-3 .md\:grid-cols-3 |
lg: | ≥ 1024px | .lg\:col-4 .lg\:grid-cols-4 |
Component Model
Every EXSA component follows the same pattern:
- One CSS file per component —
components/buttons.css,components/modal.css - BEM naming —
.card,.card__title,.card--hoverable - Zero specificity — all component rules use
:where() - Token-driven — colors, spacing, shadows reference CSS custom properties
- Modifier classes — variants use
--suffix:.btn--primary,.alert--success,.tabs--vertical
/* What a component looks like internally */
:where(.card) {
background: var(--color-bg);
border: 1px solid var(--color-bg-secondary);
border-radius: var(--border-radius);
}
:where(.card--hoverable:hover) {
box-shadow: var(--box-shadow) var(--color-shadow);
}
BEM Naming Convention
EXSA uses BEM (Block, Element, Modifier) for all component classes. It's the simplest way to guarantee zero naming collisions across 49 components — no build tool required.
The three rules
| Part | Pattern | Example | Means |
|---|---|---|---|
| Block | .block | .card | The component root |
| Element | .block__element | .card__title | A child of the block |
| Modifier | .block--modifier | .card--hoverable | A variant or state |
Why not utility classes? Why not CSS Modules?
| Approach | Needs build step? | Naming collisions? | Token-friendly? |
|---|---|---|---|
| BEM (EXSA) | No | No — unique prefixes | Yes — all values are var(--token) |
| Utility (Tailwind) | Required | No — atomic classes | No — hardcoded values |
| CSS Modules | Required | No — auto-scoped | Yes — can use var() |
| Scoped (Vue/Svelte) | Framework-dependent | No — auto-scoped | Yes — can use var() |
Abbreviated modifiers
For common variants, EXSA uses short, memorable modifier names:
| Modifier | Used on | Means |
|---|---|---|
--sm / --lg / --xl | Most components | Size variants |
--primary / --success / --danger / --warning | Buttons, badges, alerts | Semantic color variants |
--outline / --ghost / --soft / --surface | Buttons, alerts, dropdowns | Style variants |
--vertical / --horizontal | Stepper, data-list, separator | Orientation |
--active / --disabled / --loading | Stateful components | Current state |
:where() for zero specificity, var(--token) for all values, BEM naming. Your component will feel native to EXSA and theme-switch automatically.JavaScript Behaviors
components.js provides interactive behavior for 29 components. It's class-driven — no hardcoded IDs, no configuration objects. It scans the DOM for component classes and initializes them automatically.
Components that need JS
| Component | What JS does | Lines |
|---|---|---|
| Dropdown | Toggle open/close, outside click dismiss | ~15 |
| Modal | Open/close, backdrop, Escape, focus trap | ~20 |
| Slideshow | Auto-advance, arrows, dots, pause on hover | ~30 |
| Tabs | Panel toggling, active state | ~15 |
| Toast | Create, auto-dismiss, stack | ~15 |
| Lightbox | Open/close, prev/next, keyboard nav | ~25 |
| Context Menu | Right-click trigger, position clamping | ~20 |
| Popover | Click trigger, outside/Escape close | ~15 |
| Topbar | Scroll shadow, mobile toggle, dropdowns | ~25 |
| Music Player | Play/pause toggle, time tracking | ~20 |
| And 19 more | Cookie bar, rating, stepper, drawer, color picker, date picker, password toggle, range slider, theme switcher, RTL toggle, back-to-top, video gallery, resizer, sidebar, form validation, donut chart... | ~10-20 each |
Tree-Shaking & Generator
During development, link individual component CSS files. For production, use the Generator to create a single bundle:
- Pick your theme
- Select the components you use
- Download
exsa.bundle.css+bundle.js - Replace all individual
<link>tags with one
<!-- Development: individual files -->
<link href="style.css">
<link href="themes/breeze.css">
<link href="components/card.css">
<link href="components/modal.css">
<!-- Production: one file -->
<link href="exsa.bundle.css">
Migrating from Bootstrap
| Bootstrap | EXSA | Notes |
|---|---|---|
.container | .container | Same API |
.row / .col-md-6 | .flex + .col-2 or .grid + .grid-cols-2 | No row wrapper needed |
.btn-primary | .btn .btn--primary | BEM naming, more variants |
.alert-info | .alert .alert--info | Also has soft/outline/surface styles |
.badge | .badge | Same API, more colors |
.navbar | .topbar | Fixed top, scroll shadow, mobile hamburger |
.modal | .modal | Nested dialog with header/body/footer |
.spinner-border | .spinner | 3 sizes, pure CSS |
| 160 KB | 11.8 KB core + components | ~13x smaller core |
Migrating from Tailwind
EXSA takes the opposite approach: semantic components instead of atomic utilities. Here's how the mental model translates:
| Tailwind | EXSA | Philosophy |
|---|---|---|
flex justify-between items-center gap-4 | flex justify-between items-center gap | Layout utilities are similar — EXSA uses tokens for spacing |
bg-white rounded-lg shadow-md p-6 border | card | One component class replaces 5+ utilities |
text-lg font-semibold text-gray-900 | card__title | Semantic class carries meaning |
| Edit every class to change theme | Swap one theme file | Tokens vs hardcoded values |
.flex, .grid, .gap, .text-center give you utility-class convenience. But for recurring UI patterns, EXSA's components eliminate class repetition.