Skip to content

One class. Not forty.

mCSS is a modern CSS framework and component library for websites. Real CSS, real markup, zero build step. Built on what browsers can finally do.

Get startedView on GitHub

MIT licensed No dependencies It’s just CSS

Two mCSS classes replace forty utility classes: the same button, from markup you can read.

<link rel="stylesheet" href="mcss.min.css">
Copied!

That’s the install. Download dist/mcss.min.css or copy the source files. Every modern browser understands them as-is: no compiler, no config, no node_modules.

Philosophy

Made for humans who write CSS

CSS isn’t broken, and you don’t need to be protected from it. mCSS takes care of the tedious parts (resets, tokens, a sane cascade) and gets out of the way.

  • It’s actual CSS

    No pseudo-syntax, no new mental model. If you know CSS, you already know mCSS, and everything you learn here works everywhere, forever.
  • The cascade is a feature

    Native @layer keeps specificity conflicts from ever starting: anything you write outside mCSS’s layers wins automatically. No !important, no fighting your framework.
  • Markup you can read

    One semantic class per element. Your HTML describes what things are, and six months from now you’ll still understand it.

Modern CSS

Built on what browsers can do now

The last few years quietly made CSS spectacular. mCSS is what a framework looks like when it’s designed after that happened.

  • @layer

    The whole architecture. Import order stops mattering, and your overrides always win.

    Baseline Widely available
  • light-dark()

    Dark mode is one token file, not a parallel stylesheet.

    Baseline 2024
  • :has() & nesting

    Components with zero specificity hacks, written the way you’d write them yourself.

    Baseline Widely available
  • @scope

    Prose styling that can’t leak into your components.

    Baseline 2025
  • Scroll-driven animations

    The reading progress bar on this very site: pure CSS in modern browsers, a graceful fallback elsewhere.

    Limited availability
  • Three-tier tokens

    Raw scales → semantic theme → per-component properties. Change one value; the system follows.

    Baseline Widely available

Every technique is documented on the blog. The framework practices what it teaches.

Read the blog →

Theming

Theme with variables, not variants

Every color, size, and radius flows from one token file. Edit it and the whole system follows, light and dark.

Pick a demo theme

You’re invited!

Sam turns 30 · Saturday 4pm

Cake, candles, and questionable karaoke. No gifts, just bring yourself.

We’ll never share it.Please fill out this field correctly.
/* settings.ui.css defaults (excerpt) */
:root {
  --heading-font: var(--display);
  --text: ui-sans-serif, system-ui, sans-serif;
  --text-md: 1rem;
  --text-lg: 1.2rem;
  --text-color: light-dark(#23282e, #d6dbe1);
  --card-bg-color: light-dark(#edeef1, #353c45);
  --card-border-radius: 8px;
  --card-shadow: var(--shadow-md);
  --bt-primary-background-color: #0284c7;
  --bt-primary-background-color-hover: #0ea5e9;
  --bt-primary-border-color: #0284c7;
  --bt-primary-border-color-hover: #0284c7;
  --bt-border-radius: 8px;
  --input-border-radius: 5px;
  --link-color: light-dark(#0284c7, #38bdf8);
}
/* a wireframe theme: the entire diff */
:root {
  --heading-font: ui-rounded, "Arial Rounded MT Bold", Calibri, sans-serif;
  --text-color: light-dark(#404040, #d4d4d4);
  --card-bg-color: light-dark(#f5f5f5, #171717);
  --card-border-radius: 0;
  --card-shadow: none;
  --bt-primary-background-color: #525252;
  --bt-primary-background-color-hover: #737373;
  --bt-primary-border-color: #525252;
  --bt-primary-border-color-hover: #525252;
  --bt-border-radius: 0;
  --input-border-radius: 0;
  --link-color: light-dark(#525252, #a3a3a3);
}
/* sunset: the entire diff */
:root {
  --heading-font: "Iowan Old Style", Georgia, serif;
  --text: Georgia, "Times New Roman", serif;
  --text-md: 1.05rem;
  --text-lg: 1.3rem;
  --text-color: light-dark(#431407, #ffedd5);
  --card-bg-color: light-dark(#fef9c3, #431407);
  --card-border-radius: 16px;
  --card-shadow: 0 8px 24px rgb(234 88 12 / 0.25);
  --bt-primary-background-color: #ea580c;
  --bt-primary-background-color-hover: #f97316;
  --bt-primary-border-color: #ea580c;
  --bt-primary-border-color-hover: #ea580c;
  --bt-border-radius: 1e5px;
  --input-border-radius: 1e5px;
  --link-color: light-dark(#c2410c, #fb923c);
}
Show the diff
/* settings.ui.css defaults (excerpt) */
:root {
  --heading-font: var(--display);
  --text: ui-sans-serif, system-ui, sans-serif;
  --text-md: 1rem;
  --text-lg: 1.2rem;
  --text-color: light-dark(#23282e, #d6dbe1);
  --card-bg-color: light-dark(#edeef1, #353c45);
  --card-border-radius: 8px;
  --card-shadow: var(--shadow-md);
  --bt-primary-background-color: #0284c7;
  --bt-primary-background-color-hover: #0ea5e9;
  --bt-primary-border-color: #0284c7;
  --bt-primary-border-color-hover: #0284c7;
  --bt-border-radius: 8px;
  --input-border-radius: 5px;
  --link-color: light-dark(#0284c7, #38bdf8);
}
/* a wireframe theme: the entire diff */
:root {
  --heading-font: ui-rounded, "Arial Rounded MT Bold", Calibri, sans-serif;
  --text-color: light-dark(#404040, #d4d4d4);
  --card-bg-color: light-dark(#f5f5f5, #171717);
  --card-border-radius: 0;
  --card-shadow: none;
  --bt-primary-background-color: #525252;
  --bt-primary-background-color-hover: #737373;
  --bt-primary-border-color: #525252;
  --bt-primary-border-color-hover: #525252;
  --bt-border-radius: 0;
  --input-border-radius: 0;
  --link-color: light-dark(#525252, #a3a3a3);
}
/* sunset: the entire diff */
:root {
  --heading-font: "Iowan Old Style", Georgia, serif;
  --text: Georgia, "Times New Roman", serif;
  --text-md: 1.05rem;
  --text-lg: 1.3rem;
  --text-color: light-dark(#431407, #ffedd5);
  --card-bg-color: light-dark(#fef9c3, #431407);
  --card-border-radius: 16px;
  --card-shadow: 0 8px 24px rgb(234 88 12 / 0.25);
  --bt-primary-background-color: #ea580c;
  --bt-primary-background-color-hover: #f97316;
  --bt-primary-border-color: #ea580c;
  --bt-primary-border-color-hover: #ea580c;
  --bt-border-radius: 1e5px;
  --input-border-radius: 1e5px;
  --link-color: light-dark(#c2410c, #fb923c);
}

Radio buttons and :has(): this demo runs on zero JavaScript.

Ownership

You own the code

mCSS isn’t a dependency. It’s a starting point. Copy the files into your project and edit them like the code you wrote yourself, because now it is. Styling disagreements end with you changing a line, not filing an issue.

MIT licensed. Versioned releases when you want to pull updates. No lock-in, because there’s nothing to be locked into.

  • MIT LicenseUse it anywhere. Keep it forever.
  • Versioned releasesPull updates when you choose to.
  • One token fileEdit settings.tokens.css, not node_modules.

Give your CSS its cascade back

Read the methodology, copy the files, ship something.

Prefer email? Join the mailing list: new components and modern-CSS write-ups, no noise.