CSS is Awesome

Three authoring tiers

css-is-awesome ships three ways to author the same components — drop-in classes, SCSS mixins, or zero-class bare tags. All three resolve to the same router mixin per component, so styling stays consistent across an app that mixes them.

One router mixin per component. Three doors into it. That’s the entire architecture. Add a variant to btn(variant) once and every tier picks it up.

Tier 1 — Drop-in CSS + HTML

Two stylesheets, one class per element, ship. No build, no SCSS, no framework. Audience: designers, marketing pages, prototypes, anyone without a build step.

<!-- in your <head> -->
<link rel="stylesheet" href="css-is-awesome.min.css">
<link rel="stylesheet" href="theme-sketchbook.css">

<!-- in your <body> -->
<a class="cia-btn-primary" href="/start">Get started</a>
<a class="cia-btn-outline" href="/docs">Read docs</a>
<article class="cia-card"></article>

One class per element. No BEM, no __element / --modifier chains. The cia- prefix keeps every utility and component class out of your app’s namespace.

Tier 2 — SCSS mixins + HTML

Author your own class names; the mixin handles the styling. Audience: product teams that want their own domain vocabulary in markup (hero-cta, product-card) without giving up a design system.

// app.scss
@use 'css-is-awesome/scss/components/buttons' as b;
@use 'css-is-awesome/scss/components/data'    as d;
@use 'css-is-awesome/scss/mixins'             as m;

.hero-cta {
  @include b.btn(primary, $px: 6, $r: full);
  @include m.elevation(2);
}
.checkout-cancel { @include b.btn(outline); }
.product-card    { @include d.card-base($shadow: 2); }

<!-- in your HTML -->
<a class="hero-cta" href="/buy">Buy now</a>
<a class="checkout-cancel" href="/cart">Back to cart</a>
<article class="product-card"></article>

Variant is an argument to the mixin, not a class modifier. Every parameter is overridable — the mixin accepts $px, $r, $shadow, and friends to tune one-off components without breaking the system.

Tier 3 — Bare tags (opt-in Pico-mode)

One @use line styles every common bare tag in your site — buttons, tables, inputs, forms, headings, lists. Audience: content-heavy sites, blog posts, READMEs rendered as HTML, anywhere the author doesn’t want to think about classes.

// app.scss — one line styles the whole site
@use 'css-is-awesome/scss/recipes/bare-tags';

<!-- in your HTML -->
<button>Save</button>
<button type="reset">Cancel</button>
<table></table>
<input type="email">

The recipe styles bare tags at specificity 0,0,1 — no @layer, no :where(). Any class-based selector you add wins automatically, so React + CSS Modules + third-party libs all override the recipe without ceremony.

The same button, three ways

All three of these resolve to the same btn(primary) mixin output. Visually identical, conceptually different.

<!-- Tier 1 -->
<button class="cia-btn-primary">Save</button>

<!-- Tier 2 -->
<button class="save-btn">Save</button>
// app.scss
.save-btn { @include b.btn(primary); }

<!-- Tier 3 -->
<button>Save</button>

Architecture

Change the router, every tier updates. Add a variant once, every tier gets it. That’s the entire payoff.

Picking a tier

You’re building…Use
A landing page, prototype, or static site with no buildTier 1
A product app where designers want semantic class namesTier 2
A content site, blog, or generated HTML where classes are noiseTier 3
A React or Next.js appTier 4 — see install

Tiers compose. A Tier 2 product can drop in a Tier 3 recipe for its /blog route, and a Tier 1 marketing page can sit next to a Tier 4 app under the same theme file.

Theme