decor.css
v1.0.0
Published
A pure-CSS, zero-JavaScript UI library with pro tools — one link tag and your site looks designed.
Maintainers
Readme
decor.css
One link tag, and your site looks designed.
A pure-CSS, zero-JavaScript UI library with pro tools. Opinionated components, design tokens, layout utilities, automatic dark mode — plus a CLI for custom bundles and class linting.
Demo · Docs · Install · Components · Pro tools · Theming
Why decor.css
- Zero JavaScript. Navbar collapse, tabs, accordions and invalid-form states are pure CSS — modern
:has(), hidden-checkbox patterns,<details>— and modals are styled via the native<dialog>. - Beautiful by default. A distinctive "Sage Green" + warm gold palette in OKLCH, fluid
clamp()type, soft layered shadows, tasteful motion. - Ridiculously small. 6.5 kB gzipped for all 17 components (Bootstrap's full build is ~70 kB) — and the CLI can trim it further.
- Pro tools included. A real
decorCLI: custom bundles, token overrides, a class linter and a dev server — runs on plain Node. - Automatic dark mode via
prefers-color-scheme, plus manual.dc-dark/.dc-lightoverrides. - Accessible. 44px touch targets, visible focus rings everywhere, AA-contrast color pairs in both themes,
prefers-reduced-motionsupport. - Low specificity. Single classes, no
!important(one documented exception), no IDs — override anything with ease.
Install
npm install decor.cssOr via CDN — the jsdelivr field in package.json means this just works:
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/decor.css@latest/dist/decor.min.css"
/>
<!-- or unpkg -->
<link
rel="stylesheet"
href="https://unpkg.com/decor.css@latest/dist/decor.min.css"
/>No build step required — a raw <link> is enough.
Quick start
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/decor.css@latest/dist/decor.min.css"
/>
</head>
<body>
<section class="dc-hero">
<h1>Hello, world.</h1>
<p class="dc-text-soft">It already looks designed.</p>
<a class="dc-btn dc-btn--lg" href="#">Get started</a>
</section>
</body>
</html>💡 See the live demo for every component, or the docs for install/CLI/theming guides. Run
npx decor serveto view both locally.
Dark mode
Dark mode follows your OS automatically. Force either theme manually:
<html class="dc-dark">
<!-- always dark -->
<html class="dc-light">
<!-- always light -->
</html>
</html>Components
| Component | Class | Variants / sizes |
| ---------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------- |
| Button | .dc-btn | primary · secondary · ghost · outline · danger; sm · md · lg; .dc-btn-group, .dc-btn--block |
| Form | .dc-input .dc-textarea .dc-select .dc-checkbox .dc-radio .dc-label | .dc-field, .dc-hint, .dc-error, .dc-field--invalid |
| Card | .dc-card | .dc-card-header · .dc-card-body · .dc-card-footer; .dc-card--hover |
| Navbar | .dc-nav | .dc-nav-brand · .dc-nav-links · CSS-only burger collapse |
| Badge | .dc-badge | success · warning · danger · info · neutral · outline; dot; lg |
| Alert | .dc-alert | info · success · warning · danger; .dc-alert-title |
| Table | .dc-table | hover rows; .dc-table--striped; .dc-table-wrap |
| Modal | .dc-modal | native <dialog>; .dc-modal--lg; header/body/footer |
| Tabs | .dc-tabs | zero-JS radio tabs; .dc-tab, .dc-tab-panel |
| Hero | .dc-hero | fluid headline, gradient wash, glow accents |
| Accordion | .dc-accordion | native <details>/<summary>; animated chevron |
| Tooltip | data-tooltip | attribute-driven; .dc-tooltip--bottom; arrow |
| Breadcrumb | .dc-breadcrumb | semantic <ol>; slash separators; current page |
| Pagination | .dc-pagination | 44px targets; active/disabled states |
| Progress | .dc-progress | native <progress>; 4 colors; lg |
| Skeleton | .dc-skeleton | shimmer; circle · sm · lg |
| Avatar | .dc-avatar | photos or initials; 4 sizes; 6 colors |
Pro tools — the decor CLI
Every package ships a real CLI (npx decor …). It runs on plain Node and needs no config to get started.
| Command | What it does |
| ------------- | --------------------------------------------------------------------------------------------------- |
| decor init | Scaffolds decor.config.mjs — pick your components, add --dc-* token overrides |
| decor build | Builds a custom bundle with exactly your components + overrides (with source maps) |
| decor check | Lints your markup (HTML/JSX/Vue/…) for unknown .dc-* classes — catches typos before they ship |
| decor serve | Local dev server for demo/ and docs/ (default :4173) |
$ npx decor init # create decor.config.mjs
$ npx decor build # ship a bundle trimmed to your components
$ npx decor check # every .dc-* class you use is known
$ npx decor serve # view demo + docs locallyWith a config, decor build emits a bundle with only what you need — e.g. 3 components ≈ 16.7 kB minified instead of 34 kB.
Utilities
.dc-container · .dc-grid / .dc-grid-2/3/4 · .dc-flex · .dc-flex-between · .dc-flex-center · .dc-gap-1…6 · .dc-stack / -sm / -lg · .dc-cluster · .dc-mt-1…6 · .dc-mb-1…6 · .dc-text-center / -soft / -faint / -xs…-5xl · .dc-mx-auto · .dc-visually-hidden
Theming
Every value is a --dc-* custom property. Override any token on :root (light) or in the dark blocks to re-skin the whole library:
:root {
--dc-primary: oklch(0.6 0.22 60); /* brand color → everywhere */
--dc-radius-md: 1rem; /* rounder controls */
--dc-speed: 200ms; /* calmer motion */
--dc-container-max: 80rem; /* wider content */
}
/* Dark theme overrides — manual */
.dc-dark { … }
/* Dark theme overrides — automatic (keep both blocks in sync) */
@media (prefers-color-scheme: dark) {
:root:not(.dc-light) { … }
}Components also expose scoped hooks, e.g. --dc-btn-bg, --dc-btn-fg on .dc-btn. See src/tokens.css for the full token list — or apply overrides at build time via decor.config.mjs.
How it compares
Different tools, different jobs — here's the honest positioning.
| | decor.css | Tailwind CSS | Bootstrap |
| ------------------------ | --------------------------------- | --------------------------------- | ----------------------------- |
| Philosophy | Opinionated components, zero JS | Utility classes, config-driven | Components + JS behaviors |
| JavaScript required | 0 | 0 (JIT tooling) | ~70 kB bundle |
| All-in size (min / gzip) | 34 kB / 6.5 kB | ~300 kB / ~40 kB (full utilities) | ~200 kB / ~70 kB |
| Dark mode | Automatic + manual | Manual (dark: variants) | Manual class + data-attribute |
| Native components | 17, CSS-only | Build-your-own | 30+ with JS |
| Build step | Optional (raw <link> works) | Required (JIT) | Optional (prebuilt) |
| Class linter | decor check built-in | — | — |
| Custom bundles | decor build | tailwind.config | custom.scss |
Use decor.css when you want a site that looks designed in five minutes, with the CLI ready when you need production-grade trimming and validation.
Browser support
Evergreen browsers (Chrome/Edge 105+, Firefox 121+, Safari 17.4+) — the library uses modern CSS only: oklch(), color-mix(), :has(), clamp(), :user-invalid, and the <dialog> element. Graceful fallbacks: light theme is the default everywhere, text-wrap: balance/pretty degrades to normal wrapping, and where :user-invalid isn't supported you can force the error state with .dc-field--invalid.
Development
npm install
npm run build # → dist/decor.css + decor.min.css + source maps + components/
npm run dev # rebuild on change
node scripts/cli.js --help # try the CLI locallyThe build bundles 20 source files with Lightning CSS.
License
MIT © 2026 sajjadbzrn
