EXSA
Generate custom CSS

EXSA Elements — Guarded Classless™ HTML Demo

Guarded Classless™ Elements

Every semantic HTML element below is styled automatically — no classes, no components. Just add class="exsa" to <body>. All selectors use :where() for zero specificity and :not([class]) guards — add any class to any element to opt out instantly. Powered by 82 design tokens in @layer exsa.elements.

Paragraph

Standard paragraph with margin: var(--gap-md) 0 and padding: 0. Multiple paragraphs stack with consistent vertical rhythm.

This is a standard paragraph. EXSA applies consistent vertical rhythm. This one is long enough to wrap and show line-height behavior.

A second paragraph stacks below with the same spacing — no extra classes needed.

<p>This is a standard paragraph...</p> <p>A second paragraph stacks below...</p>

Small & Mark

<small> renders muted text via --color-text-secondary. <mark> gets subtle padding for visibility. Both guarded with :not([class]).

This is small text — muted secondary color. Often used for captions or legal text.

This sentence contains highlighted text inside a paragraph.

<p><small>This is small text...</small></p> <p>This sentence contains <mark>highlighted text</mark>.</p>

KBD & Abbreviation

<kbd> renders as a keyboard key with mono font, border, and shadow. <abbr> shows dotted underline with help cursor. Both guarded with :not([class]).

Press Ctrl + S to save. Or use + S on Mac.

CSS custom properties are the design system. HTML is all you need.

<p>Press <kbd>Ctrl</kbd> + <kbd>S</kbd> to save.</p> <p><abbr title="Cascading Style Sheets">CSS</abbr> custom properties...</p>

Del & Ins

Editorial marks. <del> renders in danger color, <ins> in success color. Both guarded with :not([class]).

The old price was $29 and the new price is $19.

<p>The old price was <del>$29</del> and the new price is <ins>$19</ins>.</p>

Cite & Superscript

<cite> renders italic muted. <sup> renders as a pill badge with --color-secondary background. Both guarded.

The EXSA Philosophy

New featureBETA — superscript renders as a badge. Version 2new released today.

<p>— <cite>The EXSA Philosophy</cite></p> <p>New feature<sup>BETA</sup> — superscript as a badge.</p>

Code

Inline <code> gets accent background and mono font. <pre> blocks get padding, max-width, and overflow auto. <pre><code> combo gets wider padding and pre-wrap.

Inline code: git clone https://github.com/Saif-Almarri/exsa.git and const x = 42;

// Preformatted block — monospace, padded
function greet(name) {
  return `Hello, ${name}!`;
}
// Pre > Code block — wider padding, pre-wrap
const tokens = { '--color-link': '#118bee' };
// Change one token — every component recolors.
<p>Inline: <code>git clone https://github.com/Saif-Almarri/exsa.git</code></p> <pre>function greet(name) { ... }</pre> <pre><code>const tokens = { ... };</code></pre>

Lists & Dividers

Unordered and ordered lists with consistent padding. <hr> renders as a 1px divider with 3rem vertical margin.

Unordered

  • CSS custom properties are the design system
  • @layer enforces cascade order without specificity
  • :where() guarantees zero-specificity selectors

Ordered

  1. Link exsa.css
  2. Pick a theme
  3. Add class="exsa" to <body>

Content below the divider.

<h4>Unordered</h4> <ul> <li>CSS custom properties are the design system</li> </ul> <h4>Ordered</h4> <ol> <li>Link <code>exsa.css</code></li> </ol> <hr> <p>Content below the divider.</p>

Details / Disclosure

Native <details> with bold summary cursor. Nested details get indent + left border pipe for visual hierarchy.

Click to reveal — details/summary are styled

This content is hidden by default. The summary is bold with a cursor pointer.

Advanced configuration
Tokens

Override any of the 80 CSS custom properties in your theme file.

Components

Link individual component CSS files as needed — zero dead styles.

<details> <summary>Click to reveal</summary> <p>Hidden content here.</p> </details> <details> <summary>Advanced</summary> <details> <summary>Nested</summary> <p>Auto-indented with left border pipe.</p> </details> </details>

Cards

Auto-detected from <section> + <aside>. Container queries adapt padding at 320px/500px. Full-bleed images via negative margin tied to --card-padding. Horizontal cards auto-detect <img>/<figure>/<video> via :has().

Horizontal Card (auto-detected via :has)

<section> <aside> <h3>Standard Card</h3> <p>No image — just text.</p> </aside> <aside> <svg>...</svg> <h3>Feature Card</h3> <p>Full-bleed image at top.</p> </aside> </section> <!-- Horizontal card: :has() auto-detects media --> <section> <aside> <figure><img src="pic.jpg"></figure> <div> <h3>Horizontal Layout</h3> <p>Image left, text right.</p> </div> </aside> </section>

Callout

Auto-detected from <article> > <aside>. Tinted background, start accent, rounded corners, styled <strong> label and <code> chips. RTL-safe with border-inline-start. Recolor via --callout-accent and --callout-bg (defaults: secondary purple).

<article> <aside> <p><strong>Note:</strong> Methods return <code>?array</code> for single-row results... <a href="#">Links inside callouts</a> use the secondary color.</p> </aside> </article> <!-- Recolored via knobs --> <article> <aside style="--callout-accent:green; --callout-bg:color-mix(in srgb,green 8%,transparent);"> <p><strong>Warning:</strong> Same markup, different colors.</p> </aside> </article>

Table

Bordered table with themed header background (--color-link), cell padding, and rounded corners. display:block enables horizontal scroll on overflow. First column left-aligned via --justify-body.

FrameworkComponentsClasslessBuild StepToken-Driven
EXSA68None✅ 82 tokens
Bootstrap20+Optional
TailwindNoneRequired
Pico CSSFewNone
<table> <thead> <tr><th>Framework</th><th>Components</th></tr> </thead> <tbody> <tr><td>EXSA</td><td>68</td></tr> </tbody> </table>

Form

Card-style wrapper with border and shadow. All inputs, selects, textareas styled automatically. <fieldset> gets border + padding with bold <legend>. :invalid inputs show red border (only after user interaction via :not(:placeholder-shown)). :valid shows green.

Contact Us

All inputs styled automatically.

Preferences
Plan

<form> <header><h3>Contact Us</h3><p>All inputs styled automatically.</p></header> <label>Full Name <input type="text" placeholder="Jane Smith"></label> <label>Email Address <input type="email" placeholder="jane@example.com" required></label> <label>Password <input type="password" placeholder="••••••••"></label> <label>Department <select> <option>Engineering</option> <option>Design</option> <option>Marketing</option> </select> </label> <label>Message <textarea rows="3" placeholder="How can we help?"></textarea></label> <label>Budget Range <input type="range" min="0" max="100" value="50"></label> <fieldset> <legend>Preferences</legend> <label><input type="checkbox"> Subscribe to newsletter</label> <label><input type="checkbox"> Agree to terms</label> </fieldset> <fieldset> <legend>Plan</legend> <label><input type="radio" name="plan" checked> Starter (Free)</label> <label><input type="radio" name="plan"> Pro ($29/mo)</label> </fieldset> <label>Read-only <input type="text" value="Cannot edit this" readonly></label> <p><button type="submit">Submit</button></p> </form>

Blockquote

Large centered text with optional left border pipe. Border is opt-in via --blockquote-border (default: none). Footer renders in muted color.

"CSS custom properties are the design system. The cascade should enforce the architecture."

— EXSA Philosophy

"EXSA cut our development time in half. Pure semantic HTML, professional UI."

— Developer, Tech Startup
<!-- With left border (opt-in) --> <blockquote style="--blockquote-border: 4px solid var(--color-link)"> <p>"CSS custom properties are the design system..."</p> <footer>— EXSA Philosophy</footer> </blockquote> <!-- Without border (default) --> <blockquote> <p>"EXSA cut our development time in half..."</p> <footer>— Developer</footer> </blockquote>

Dialog

Native <dialog> with backdrop, entry animation, and responsive width. Open via showModal().

<dialog id="demo-dialog"> <h3>Dialog Title</h3> <p>Native HTML dialog with animated entry.</p> <button onclick="this.closest('dialog').close()">Close</button> </dialog> <button onclick="document.getElementById('demo-dialog').showModal()">Open</button>

Figure with Caption

Centered figure with responsive media and muted caption via --color-text-secondary.

800 × 200 placeholder
Figure caption — muted color, no margin by default.
<figure> <img src="photo.jpg" alt="Description"> <figcaption>Figure caption — muted color.</figcaption> </figure>

Buttons

Neutral bordered button with hover background change and click scale. Disabled state at 50% opacity with not-allowed cursor. For colored variants (primary, success, danger, etc.), see the Buttons component.

<button>Click Me</button> <button>Secondary Action</button> <button disabled>Disabled</button>

Auto Card Grid

3+ <article> elements in a <section> auto-detect as a responsive card grid. Powered by :has(> article:nth-child(3)). Add any class to any article to opt out.

Ship Faster

Three or more <article> elements in a <section> auto-detect as a responsive card grid.

Zero Classes

No .grid. No .flex. No .card. The framework detects layout intent from structure alone.

Responsive

Cards wrap automatically. Two per row on tablets, one per row on phones.

Opt Out

Add class="anything" to any article and the whole grid steps aside.

<section> <article> <h3>Ship Faster</h3> <p>Auto card grid from 3+ articles.</p> </article> <article>...</article> <article>...</article> </section>

Auto Stats Row

3+ standalone <p> elements in a <section> auto-detect as a statistics row. Powered by :has(> p:nth-child(3)).

68Components

20Themes

82Tokens

0Build Steps

<section> <p><strong style="font-size:var(--font-size-2xl);display:block;">68</strong>Components</p> <p><strong style="font-size:var(--font-size-2xl);display:block;">20</strong>Themes</p> <p><strong style="font-size:var(--font-size-2xl);display:block;">82</strong>Tokens</p> <p><strong style="font-size:var(--font-size-2xl);display:block;">0</strong>Build Steps</p> </section>

Auto Hero Split

A <header> inside <main> that contains an image/figure auto-splits into two equal columns. Powered by :has(> img, > figure, > svg, > video). Scoped to main header to avoid conflicting with the Hero component.

Image + Text, Auto-Split

When a header inside main contains an image or figure, EXSA auto-detects it and splits into two equal columns.

HeroAuto-detected
<header> <div> <h2>Image + Text, Auto-Split</h2> <p>Header with image auto-detected...</p> <button>Take the Tour</button> </div> <figure> <img src="hero.jpg" alt=""> </figure> </header>

This is a Dialog

Native HTML dialog with animated entry, backdrop, and scrollable content. EXSA adds border, radius, and scroll behavior.