Reading width
Use .prose on an article for a comfortable measure. Headings and paragraphs inside pick up a bit more vertical rhythm.
v0.5.0 · ~11kb gzipped
We don't flash, we deliver!
Compact CSS UI kit — blue primary, tokens, auto dark mode. Overlays open when you add .open (the demo script below is only a preview).
Card title
With subtitle
Shadow deepens on hover. No JS, no jumping.
Badges inside
active failed draft
| Plan | Price | Status |
|---|---|---|
| Free | $0 | active |
| Pro | $20 | selected |
| Team | $75 | draft |
Pure CSS charts — data lives in inline custom properties: --v (0–100) for bars, rings and sparklines, --v1…--v6 for donut segments, --sv for stacked shares.
Weekly sales
.chart-bars / .bar · value via --v
Traffic sources
.donut + .legend · segments via --v1…--v6
Revenue by quarter
.bar.stacked · shares via --sv, total via --v
Skill match
.chart-hbars / .hbar
Last 14 days
Toast
Neutral dark toast.
Primary
Brand colored.
Success
Saved.
Modal title
Toggle .open on .modal from your click handler.
Expand/collapse with native details — no JS.
Another panel.
Add .open on .pop from a click handler.
Bottom sheet
Toggle .open on .sheet.
Skeleton
Empty + spinner
No projects
Create one to get started.
Status + badge
Online
Away
Busym-flex-1 filler
text takes remaining space
m-row / m-col are directional flex containers; children share space equally.
m-b-10 margin-bottom: 10px
p-10 padding: 10px
m-t-5 + p-x-5 on this line
Inbox 12 · Alerts 3 · New 1
New API
v0.5 ships overlay .open.
Paid
Invoice #1042
Failed
Card was declined.
The best UI kit is the one you can paste into any stack.
h1
h2
h3
h4
h5
h6
p
Body copy at 16px. Mates styles native tags first — this is a plain paragraph with a link inside.
small
Small print sits at body size with muted color.
a
hr
blockquote
A pull quote. Native blockquote — no class.
ul
ol
kbd
Ctrl K
.kbd-row
⌘K
mark
Highlight this phrase in a sentence.
code
import "mates-css"
pre
npm install mates-css
dl
.overline
Section label
.muted
Secondary body color.
.subtle
Tertiary / hint color.
.mono
0123456789 --m-fs
.text-sm
Small utility text.
.text-lg
Large utility text.
.fw-500
Medium weight.
.fw-700
Bold weight.
.tabular
$1,240.00 $98.50 $12,004.00
.truncate
This line is clipped with an ellipsis when it overflows the box.
.clamp-2
Two-line clamp. Extra words wrap once, then the rest is cut off so the block never grows past two lines of copy in the demo.
.clamp-3
Three-line clamp. This paragraph is long enough to wrap past three lines so you can see the clamp take effect on the last visible line with an ellipsis at the end of the block.
.center
Centered line.
.prose
Use .prose on an article for a comfortable measure. Headings and paragraphs inside pick up a bit more vertical rhythm.
Reusable layout and spacing classes — not components. Class on the left, CSS on the right.
| Class | CSS |
|---|---|
.m-flex | display: flex |
.m-inline-flex | display: inline-flex |
.m-flex-row | flex-direction: row |
.m-flex-col | flex-direction: column |
.m-flex-wrap | flex-wrap: wrap |
.m-flex-nowrap | flex-wrap: nowrap |
.m-flex-1 | flex: 1 1 0%; min-width: 0 |
.m-flex-auto | flex: 1 1 auto |
.m-flex-none | flex: none |
.m-grow | flex-grow: 1 |
.m-shrink-0 | flex-shrink: 0 |
.m-basis-0 | flex-basis: 0 |
.m-order-first | order: -1 |
.m-order-last | order: 99 |
Short aliases: .m-i-* = .m-items-*, .m-j-* = .m-justify-*.
| Class | CSS |
|---|---|
.m-items-start / .m-i-start | align-items: flex-start |
.m-items-center / .m-i-center | align-items: center |
.m-items-end / .m-i-end | align-items: flex-end |
.m-items-stretch / .m-i-stretch | align-items: stretch |
.m-items-baseline / .m-i-baseline | align-items: baseline |
.m-self-start | align-self: flex-start |
.m-self-center | align-self: center |
.m-self-end | align-self: flex-end |
.m-justify-start / .m-j-start | justify-content: flex-start |
.m-justify-center / .m-j-center | justify-content: center |
.m-justify-end / .m-j-end | justify-content: flex-end |
.m-justify-between / .m-j-between | justify-content: space-between |
.m-justify-around / .m-j-around | justify-content: space-around |
.m-justify-evenly / .m-j-evenly | justify-content: space-evenly |
.m-j-center-v | justify-content: center |
.m-content-start | align-content: flex-start |
.m-content-center | align-content: center |
.m-content-between | align-content: space-between |
.m-grid-cols-2|3|4 collapse to one column under 640px.
| Class | CSS |
|---|---|
.m-grid | display: grid |
.m-inline-grid | display: inline-grid |
.m-grid-cols-2 | grid-template-columns: repeat(2, minmax(0, 1fr)) |
.m-grid-cols-3 | grid-template-columns: repeat(3, minmax(0, 1fr)) |
.m-grid-cols-4 | grid-template-columns: repeat(4, minmax(0, 1fr)) |
.m-grid-cols-auto | grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)) |
.m-grid-cols-auto-sm | repeat(auto-fit, minmax(11rem, 1fr)) |
.m-grid-cols-auto-lg | repeat(auto-fit, minmax(22rem, 1fr)) |
.m-grid-rows-2 | grid-template-rows: repeat(2, minmax(0, 1fr)) |
.m-grid-rows-3 | grid-template-rows: repeat(3, minmax(0, 1fr)) |
.m-grid-flow-dense | grid-auto-flow: row dense |
.m-col-span-2 | grid-column: span 2 |
.m-col-span-3 | grid-column: span 3 |
.m-col-span-full | grid-column: 1 / -1 |
.m-row-span-2 | grid-row: span 2 |
.m-grid-auto | display: grid; columns auto-fit 16rem; gap: var(--m-gap, 1rem) |
| Class | CSS |
|---|---|
.m-row | display: flex; flex-wrap: wrap; align-items: center; gap: var(--m-gap, 1rem) |
.m-col | display: flex; flex-direction: column; gap: var(--m-gap, 1rem) |
.m-row-nowrap | flex-wrap: nowrap |
.m-col-auto | on a child of .m-row: flex: 0 0 auto; width: auto |
.c-1 … .c-12 | flex: 0 0 / max-width 8.333% … 100% |
.m-g-0 | --m-gap: 0 |
.m-g-xs | --m-gap: .4rem |
.m-g-sm | --m-gap: .65rem |
.m-g-lg | --m-gap: 1.75rem |
.container | max-width: 72rem; margin-inline: auto; padding-inline: 1.25rem |
| Class | CSS |
|---|---|
.m-gap-0 | gap: 0 |
.m-gap-xs | gap: .4rem |
.m-gap-sm | gap: .65rem |
.m-gap | gap: 1rem |
.m-gap-lg | gap: 1.75rem |
.m-gap-xl | gap: 2.5rem |
.m-gap-5 .m-gap-10 .m-gap-15 .m-gap-20 .m-gap-30 .m-gap-40 | gap: 5px … 40px |
.m-gap-x-* | column-gap (same named + px scale) |
.m-gap-y-* | row-gap (same named + px scale) |
Scale: 0 = 0, 5 = 5px, 10 = 10px, 15 = 15px, 20 = 20px, 30 = 30px, 40 = 40px. Sides: t top, b bottom, l left, r right, x left+right, y top+bottom.
| Class | CSS |
|---|---|
.m-0 … .m-40 | margin: 0 … margin: 40px |
.m-t-0 … .m-t-40 | margin-top |
.m-b-0 … .m-b-40 | margin-bottom |
.m-l-0 … .m-l-40 | margin-left |
.m-r-0 … .m-r-40 | margin-right |
.m-x-0 … .m-x-20 | margin-left + margin-right |
.m-x-auto | margin-left: auto; margin-right: auto |
.m-y-0 … .m-y-20 | margin-top + margin-bottom |
Same numeric scale and side letters as margin.
| Class | CSS |
|---|---|
.p-0 … .p-40 | padding: 0 … padding: 40px |
.p-t-* | padding-top |
.p-b-* | padding-bottom |
.p-l-* | padding-left |
.p-r-* | padding-right |
.p-x-* | padding-left + padding-right |
.p-y-* | padding-top + padding-bottom |
| Class | CSS |
|---|---|
.m-w-auto | width: auto |
.m-w-xs | width: 8rem |
.m-w-sm | width: 12rem |
.m-w-md | width: 18rem |
.m-w-lg | width: 26rem |
.m-w-full | width: 100% |
| Class | CSS |
|---|---|
.surface | background: var(--m-surface) |
.elev-1 | box-shadow: var(--m-shadow) |
.elev-2 | box-shadow: var(--m-elev) |
.elev-3 | box-shadow: 0 8px 28px rgba(16,24,40,.18) |
.border | border: 1px solid var(--m-border) |
.radius-sm | border-radius: var(--m-r-sm) |
.radius | border-radius: var(--m-r) |
.radius-full | border-radius: var(--m-r-full) |
.center | text-align: center |
.muted | color: var(--m-fg-2) |
.subtle | color: var(--m-fg-3) |
.mono | font-family: var(--m-mono) |
.overline | uppercase, tracked, color: var(--m-fg-3) |
.text-sm | font-size: 1rem |
.text-lg | font-size: 1.25rem |
.fw-500 | font-weight: 500 |
.fw-700 | font-weight: 700 |
.tabular | font-variant-numeric: tabular-nums |
.truncate | overflow: hidden; text-overflow: ellipsis; white-space: nowrap |
.clamp-2 | 2-line clamp |
.clamp-3 | 3-line clamp |
.hidden | display: none !important |
.rel | position: relative |
.abs | position: absolute |
.fixed | position: fixed |
.inset-0 | inset: 0 |
.z-10 .z-20 .z-50 | z-index: 10 / 20 / 50 |
.sticky-t | position: sticky; top: 0 |
.sticky-b | position: sticky; bottom: 0 |
.aspect | aspect-ratio: 16 / 9 |
.aspect-1x1 | aspect-ratio: 1 |
.aspect-4x3 | aspect-ratio: 4 / 3 |
.aspect-16x9 | aspect-ratio: 16 / 9 |
.scroll-y | overflow-y: auto |
.no-scrollbar | hides scrollbars |
.overscroll-none | overscroll-behavior: none |
.divider | horizontal rule with optional label |
.sr-only | visually hidden, available to AT |
.skip-link | off-screen until focused |
.is-disabled | opacity: .5; pointer-events: none |
.is-loading | opacity: .7; pointer-events: none |
.print-only | hidden on screen, shown in print |
.no-print | hidden in print |