Write HTML.
Not class soup.
mode.css styles semantic HTML out of the box, then lets you compose
everything with a tiny family of µ-* attributes — no classes,
no build step, no runtime.
Introduction
One stylesheet turns plain, semantic markup into a polished, responsive,
themeable page. You never touch a class attribute.
Most CSS frameworks ask you to decorate every element with a string of utility classes. mode.css takes the opposite bet: your HTML should describe meaning, and the cascade should handle appearance. The entire library is built around a single principle — a strong attribute cascade.
| Instead of | You write |
|---|---|
<div class="grid grid-cols-3 gap-6"> |
<section µ-grid="3-col"> |
<div class="card border rounded shadow p-4"> |
<article> |
<h3 class="text-xl font-bold mb-2"> |
<h3> |
Installation
Add one <link>. There is no build step and nothing to configure.
From the CDN
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/microdom/mode.css/dist/mode.min.css">
Local file
<link rel="stylesheet" href="dist/mode.css">
Your first page
This is a complete, responsive page — sticky header with a no-JS hamburger menu, a centered reading column and a footer:
Hello, cascade
Native elements are styled automatically — no classes, no setup.
<body>
<input type="checkbox" id="menu-toggle" hidden>
<header>
<div>
<b>My Site</b>
<label for="menu-toggle"><span></span></label>
<nav><ul><li><a href="#">Home</a></li></ul></nav>
</div>
</header>
<main>
<section>
<h1>Hello, cascade</h1>
<p>Native elements are styled automatically.</p>
<button>A native button</button>
</section>
</main>
<footer><div><p>© 2026</p></div></footer>
</body>
The mental model
Everything you style lives in one of three attribute layers. Master these and you know the whole library.
| Layer | Role | Example |
|---|---|---|
| 1 · Structure | A bare attribute that establishes a layout. | <section µ-grid> |
| 2 · Modifier | Space-separated tokens that mutate the structure. | µ-grid="3-col cards" |
| 3 · Semantic | A domain attribute describing what the element is. | µ-pricing |
The one naming rule
Attribute values name the thing, never a CSS property. If a value reads like a Tailwind utility, it's wrong.
| Example | Why | |
|---|---|---|
| ✓ do | µ-grid="pricing" | Describes the block. |
| ✗ don't | µ-grid=" | That's a property, not a thing. |
| ✗ don't | | Utility class in disguise. |
The page skeleton
mode.css homologates three pillars — header, main and
footer — so content always lines up on the same lateral gutter.
Direct children of <body> share --screen-padding, and the
real content centers inside --max-width. A <section> spans
the full width, so its background can bleed edge-to-edge while its text stays aligned.
<body>
<header><div> … brand + nav … </div></header>
<main>
<section> … reading content … </section>
</main>
<footer><div> … </div></footer>
</body>
Grids
A bare µ-grid is auto-responsive. Add a column token to take control.
Auto grid (default)
With no value, the grid auto-fits as many 280px+ columns as will fit.
Auto
Fits to space.
Fit
No breakpoints to manage.
Flow
Wraps when it needs to.
<section µ-grid>
<article><header><h3>Auto</h3></header><p>Fits to space.</p></article>
<article> … </article>
</section>
Explicit columns
Tokens 2-col through 6-col set a fixed track count that
collapses gracefully on smaller screens (1 → 2 → full).
One
3-col on desktop.
Two
2-col on tablet.
Three
1-col on mobile.
<section µ-grid="3-col">
<article> … </article>
<article> … </article>
<article> … </article>
</section>
| Token | Desktop columns |
|---|---|
µ-grid | auto-fit (min 280px) |
2-col … 6-col | 2 – 6 fixed tracks |
sidebar-left | narrow rail + wide content |
sidebar-right | wide content + narrow rail |
Native elements
Headings, text, links, buttons and form fields are styled with zero attributes. These are the building blocks every layout inherits.
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<p>Body text with a <a href="#">link</a>.</p>
<button>Primary action</button>
Cards
Any <article> inside a µ-grid becomes a card — a
flex column with border, padding and radius. Use <header>,
<p> and <footer> for consistent rhythm.
Starter
Everything you need to ship a small site.
Pro
For teams that need more room to grow.
<section µ-grid="2-col">
<article>
<header><h3>Starter</h3></header>
<p>Everything you need to ship a small site.</p>
<footer><button>Choose</button></footer>
</article>
<article> … </article>
</section>
<footer> button stretches to the card width automatically.Forms
A <form> is a grid; wrap each field in a <label>
and everything aligns with shared focus styles.
<form>
<label>Full name <input type="text"></label>
<label>Plan
<select><option>Starter</option></select>
</label>
<label>Message <textarea></textarea></label>
<button type="submit">Send</button>
</form>
Tokens & theming
Every visual decision is a CSS custom property. Override them in :root —
no recompilation, no config file.
:root {
--color-bg: #ffffff;
--color-text: #1f2937;
--color-accent: #111827;
--spacing: 1.5rem; /* master rhythm unit */
--radius: 6px;
--max-width: 1200px; /* reading column */
--screen-padding: 1.5rem; /* shared gutter */
}
| Token | Controls |
|---|---|
--font-main | Base font stack |
--size-h1 … --size-small | Harmonic type scale |
--color-bg / text / muted / border / accent | Color system |
--spacing | Master spacing (scales up at breakpoints) |
--radius | Global corner radius |
--max-width | Reading-column width |
--screen-padding | Lateral gutter for the three pillars |
Dark mode
A checkbox and one CSS rule — no JavaScript. (This very page uses it; try the ◐ / ◑ toggle in the header.)
<!-- in your markup -->
<input type="checkbox" id="theme-toggle" hidden>
<label for="theme-toggle">Toggle theme</label>
/* in your theme.css */
body:has(#theme-toggle:checked) {
--color-bg: #0b0d12;
--color-text: #c9d1d9;
--color-accent: #f3f6fb;
}
Because every component reads from the same tokens, re-painting the whole site is just a matter of swapping a handful of variables.
Migrating to mode
Refactoring class-heavy markup is mostly deletion. Flatten the divs, drop the classes, and let the cascade do the work.
Before — utility soup
<div class="grid grid-cols-3 gap-6 bg-gray-100 p-8 rounded-lg">
<div class="border p-4 rounded bg-white shadow">
<h3 class="text-xl font-bold text-blue-600 mb-2">Client</h3>
<p class="text-sm text-gray-600">Description…</p>
</div>
</div>
After — mode.css
<section µ-grid="3-col cards">
<article>
<h3>Client</h3>
<p>Description…</p>
</article>
</section>
Aesthetics that the defaults don't cover (a brand color, a special card treatment) live in your theme layer, keyed off the Layer-3 attribute:
[µ-grid~="cards"] article {
box-shadow: var(--shadow-sm);
border-radius: var(--radius);
}