Write HTML.
It comes out finished.
fertig turns semantic HTML into polished interfaces. Forms, data views, dialogs, and popovers arrive themed and responsive from one 9.3 KB CSS file — no runtime.
Start building See every componentComponents
npm install fertig Edit HTMLPreview instantly
- 9.3 KB
- gzipped
- 0
- JavaScript
- 0
- dependencies
- 0
- required classes
01 — Live system
A finished UI, from one file.
Try a category or accent. Every control is real semantic HTML styled by the same file you came here to download.
default paid overdue
$48,200
$9,400
94%
| Invoice | Client | Amount | Status |
|---|---|---|---|
| INV-0231 | Acme Corp | $4,200.00 | overdue |
| INV-0232 | Globex | $12,850.00 | paid |
| INV-0233 | Initech | $980.00 | sent |
| Total | $18,030.00 | ||
This paragraph is a skeleton placeholder.
02 — Native behaviour
No runtime. Real behaviour.
fertig uses the browser features you already ship —
popover, command, anchor positioning — so
menus, dialogs, drawers, and disclosures work without a JavaScript
controller. The table records an audit with scripting disabled.
| Popover menu | works — anchored to its button |
|---|---|
| Dialog | works — opens and closes through command |
| Drawer | works — the same dialog, docked to an edge |
| Toast | works — a non-modal popover in the corner |
| Tooltip | works — one attribute, pure CSS |
| Disclosure | works — native <details>, animated to auto height |
| Tabs | styled only — honest selection and keyboard behavior need a controller |
Tabs are the deliberate exception:
CSS cannot update aria-selected, manage roving focus or
implement arrow-key navigation. The short controller is in
the docs.
03 — Design principles
Small enough to forget. Finished enough to ship.
Most are either too plain to ship or too heavy to justify. fertig sits between them: opinionated enough to look finished, small enough that you never think about it again.
Bidirectional
Written in logical properties throughout, so dir="rtl"
mirrors the whole sheet — Persian and Arabic get the same layout,
not a patched one. Verified by rendering a Persian page in both
directions.
Classless
Semantic tags are styled directly. Seven optional classes and a compact set of layout utilities exist if you want them — you can ignore every one and the page still looks finished.
Modern only
OKLCH, light-dark(), cascade layers, anchor
positioning, container queries, @property. No vendor
prefixes except the three no engine has replaced.
Accessible
Every colour pair the sheet uses clears WCAG AA in both themes, at rest and on hover — measured, not assumed. The tightest pairing is text on the amber fill in light mode at 5.41:1.
Overridable
The sheet is wrapped in @layer fertig, so your own
unlayered CSS wins at any specificity. There is no
!important anywhere in it.
04 — Component layer
Modern primitives. Still just HTML.
Compound fields, selectable lists, surfaces, items, and avatars use native elements and ARIA as their API. The result feels like a UI kit without adding a component runtime.
- AMAda Morris
- LKLin Kim
- SRSam Rivera
05 — Your system
Tune the system, not every component.
Move a few tokens and the live panel follows. Accent contrast is measured as you go, so the result stays usable in both themes.
06 — Questions
Does it really need no classes?
None. Every element in the semantic set is styled by its tag. The seven classes and the layout utilities are there for the cases where HTML has no element for what you mean — a row of buttons, a card — and you can build a whole site without touching them.
How do I override something?
Write ordinary CSS. The sheet lives in @layer fertig,
so any unlayered rule of yours wins regardless of specificity. Most
customisation is a token: set --fertig-ac for the accent,
--fertig-w for the toolbar column, --fertig-f for the type.
What about older browsers?
They get plain but readable HTML. The sheet runs in any browser
released since August 2024 — Chrome 123, Safari 17.5, Firefox 129 —
and the only thing it carries for the ones before them is a flat
sRGB palette, so a missing light-dark() cannot leave a
page unreadable. No polyfills, no fallback build. That policy is the
reason it is 9.3 KB rather than 20.
Can I change the colours?
Yes. The palette is seven OKLCH ramps of five steps, and the
semantic tokens are built from them with light-dark().
Override --fertig-ac alone and the buttons, focus rings,
links, selection and caret all follow.
07 — Install
One stylesheet. Start shipping.
Package
npm install fertig CDN
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/fertig/fertig.min.css">