Skip to content

One class. Not twenty.

mCSS is a CSS framework and component library for websites. It gives each element one semantic class, keeps its own rules in cascade layers, and needs no build step.

Get startedView on GitHub

One mCSS class replaces 23 utility classes on the same button.

  • ~16 KB min+gzip
  • Components ~5 KB
  • 0 dependencies
  • Baseline 2024
  • MIT licensed

Your overrides work the first time

mCSS puts all of its own CSS in native @layer cascade layers, so specificity conflicts never start: anything you write outside those layers wins automatically. No !important, no fighting your framework.

  1. helpers!important, opt-in
  2. your CSSno layer
  3. externalthird-party CSS
  4. theme.useryour theme
  5. theme.defaultevery design value
  6. componentsthe component library
  7. globallayouts, prose, a11y
  8. elementsHTML element defaults
  9. basereset
/* mcss.css: the framework's layers, lowest first */
@layer base, elements, global, components, theme.default, theme.user, external, helpers;

/* your CSS: no layer */
/* <a class="bt bt-primary signup_cta"> */
.signup_cta {
  border-radius: 0; /* beats .bt.bt-primary */
}

Built with modern CSS

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

Modern CSS features mCSS is built on, and their browser support
FeatureWhat mCSS does with itSupport
@layerThe whole architecture. Import order stops mattering, and your overrides always win. Baseline Widely available (opens in a new tab)
light-dark()Dark mode lives in the same tokens: each color holds its light and its dark value. Baseline 2024 (opens in a new tab)
:has() & nestingComponents with zero specificity hacks, written the way you’d write them yourself. Baseline Widely available (opens in a new tab)
@scopeProse styling that can’t leak into your components. The one feature here newer than the Baseline 2024 floor. Baseline 2025 (opens in a new tab)
@containerLayouts that size their columns to the space they’re in. Baseline Widely available (opens in a new tab)
Custom propertiesThree tiers of tokens: raw scales, semantic theme values, and per-component properties. Baseline Widely available (opens in a new tab)

Learn more about modern CSS practices on the blog →

Make it your own with built-in themes

Every color, size, and radius comes from one token file, in light and dark. Start from a theme, change a value, and every component that uses it changes with it.

Pick a demo theme

Default and Wireframe ship with mCSS, Sunset is made up for this page.

theme.default.css, excerpt
:root {
  --text: ui-sans-serif, system-ui, sans-serif;
  --heading-font: var(--display);
  --primary-600: #0284c7;
  --border-sm: 1px;
  --ui-border-color: light-dark(var(--base-200), var(--base-500));
  --card-border-radius: var(--radius-lg);
  --card-shadow: var(--shadow-md);
  --bt-border-radius: var(--radius-lg);
  --bt-primary-background-color: var(--primary-600);
  --input-border-radius: var(--radius-md);
}
theme.wireframe.css, excerpt
:root {
  --text: "Comic Sans MS", "Chalkboard SE", Chalkboard, "Comic Neue", "Segoe Print", "Bradley Hand", casual, cursive;
  --heading-font: var(--text);
  --heading-weight: var(--bold);
  --primary-600: #525252;
  --border-sm: 2px;
  --ui-border-color: light-dark(var(--base-800), var(--base-200));
  --wobble-1: 115px 8px 95px 9px / 7px 110px 8px 125px;
  --wobble-2: 9px 105px 7px 120px / 115px 8px 100px 9px;
  --wobble-3: 100px 9px 120px 7px / 8px 90px 10px 110px;
  --card-border-radius: var(--wobble-2);
  --bt-border-radius: var(--wobble-1);
  --input-border-radius: var(--wobble-3);
  --ui-shadow-color: light-dark(rgb(0 0 0 / 0.85), rgb(255 255 255 / 0.55));
  --shadow-md: 4px 4px 0 var(--ui-shadow-color);
}
theme.sunset.css, excerpt
:root {
  --heading-font: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
  --heading-weight: var(--semi-bold);
  --base-50: #fbf3ea;
  --base-950: #1d1520;
  --primary-700: #b23a26;
  --body-background-color: light-dark(var(--base-50), var(--base-950));
  --card-bg-color: light-dark(var(--base-0), var(--base-900));
  --card-border-radius: 20px;
  --card-secondary-text-color: light-dark( var(--primary-700), var(--primary-300) );
  --card-shadow: 0 1px 2px rgb(61 42 51 / 0.08), 0 18px 40px -18px light-dark(rgb(178 58 38 / 0.35), rgb(0 0 0 / 0.6));
  --bt-border-radius: 1e5px;
  --bt-primary-background-color: var(--primary-700);
  --input-border-radius: 12px;
}

You own the code

mCSS doesn’t install from a package registry. You copy its source into your project, build it with PostCSS, and edit it like any other code in it. When a default doesn’t suit you, you change that line.

  • MIT licenseUse it anywhere. Keep it forever.
  • Versioned releasesTagged on GitHub and listed in the changelog. Pull updates when you choose to.
  • One theme fileYour design lives in your theme, not in node_modules.
The files an mCSS project keeps
styles/
├── framework/              # copied once, yours to edit
│   ├── mcss.css
│   ├── settings.*.css
│   ├── base.reset.css
│   ├── elements.*.css
│   ├── global.*.css
│   ├── component.*.css
│   ├── help.*.css
│   └── theme.*.css
├── site/
│   ├── theme.mysite.css    # your design lives here
│   └── component.*.css
└── main.css

Give your CSS its cascade back

Two lines in your <head> link the compiled framework and, if you want them, the components, with no build step. The docs cover the other installs, including how to build from source with PostCSS.

<!-- mCSS, ~16 KB min+gzip -->
<link rel="stylesheet" href="/css/mcss.min.css" />
<!-- components, ~5 KB -->
<link rel="stylesheet" href="/css/mcss.components.min.css" />

Get mcss.min.css and mcss.components.min.css on GitHub.

Get startedView on GitHub

Prefer email? Join the mailing list (opens in a new tab) for new components and modern CSS write-ups.