Foundations / Helpers
One class. One job. Straight from a token.
Utilities are the stagehands of the system: small, single-purpose classes that do exactly one thing and take no bow. One aligns a row, one spaces two cards, one hides a label from sight while keeping it for a screen reader. This is a curated set, not a dump, and every value traces back to a token. If a helper would type 16px by hand instead of reading --space-4, it does not belong here.
Token, utility, or component
Three layers carry style, and choosing the right one is most of the craft. Reach for the layer that answers the question you actually have.
--space-4, --color-primary, --radius-lg. Everything else points back here..gap-4 sets gap: var(--space-4). A quick, local fix in markup..gap-4 { gap: var(--space-4); }Reads the token, so one change to the scale updates every gap at once..gap-4 { gap: 16px; }A hand-typed pixel drifts from the token and quietly breaks the system.The catalog
Every class below is one declaration, and every sized value traces to a token. These stay in markup so you read the layout at a glance.
Display
| Class | Declaration |
|---|---|
.d-none | display: none |
.d-block | display: block |
.d-inline | display: inline |
.d-inline-block | display: inline-block |
.d-flex | display: flex |
.d-inline-flex | display: inline-flex |
.d-grid | display: grid |
Flexbox
| Class | Declaration |
|---|---|
.flex-row | flex-direction: row |
.flex-col | flex-direction: column |
.flex-wrap | flex-wrap: wrap |
.flex-1 | flex: 1 1 0% |
.flex-auto | flex: 1 1 auto |
.flex-none | flex: none |
Alignment
| Class | Declaration |
|---|---|
.items-start | align-items: flex-start |
.items-center | align-items: center |
.items-end | align-items: flex-end |
.justify-center | justify-content: center |
.justify-between | justify-content: space-between |
.justify-end | justify-content: flex-end |
Layout & overflow
| Class | What it does |
|---|---|
.w-full | width: 100% |
.h-full | height: 100% |
.min-w-0 | Lets a flex child shrink so truncation works. |
.overflow-auto | overflow: auto |
.truncate | One line, ellipsis: hidden overflow, nowrap, ellipsis, together. |
Gap (every step is a token)
| Class | Token | Value |
|---|---|---|
.gap-1 | var(--space-1) | 0.25rem |
.gap-2 | var(--space-2) | 0.5rem |
.gap-3 | var(--space-3) | 0.75rem |
.gap-4 | var(--space-4) | 1rem |
.gap-6 | var(--space-6) | 1.5rem |
.gap-8 | var(--space-8) | 2rem |
Typography
| Class | Token or property |
|---|---|
.text-center | text-align: center |
.text-sm | var(--font-size-sm) |
.text-base | var(--font-size-base) |
.text-lg | var(--font-size-lg) |
.text-xl | var(--font-size-xl) |
.font-medium | var(--font-weight-medium) |
.font-semibold | var(--font-weight-semibold) |
.font-bold | var(--font-weight-bold) |
Text color (semantic tokens only)
| Class | Token |
|---|---|
.text-primary | var(--color-text-heading) |
.text-secondary | var(--color-text-secondary) |
.text-muted | var(--color-text-muted) |
.text-error | var(--color-error-text) |
.text-success | var(--color-success-text) |
Border radius
| Class | Token | Value |
|---|---|---|
.rounded-sm | var(--radius-sm) | 0.375rem |
.rounded-md | var(--radius-md) | 0.5rem |
.rounded-lg | var(--radius-lg) | 0.75rem |
.rounded-xl | var(--radius-xl) | 1rem |
.rounded-pill | var(--radius-pill) | 9999px |
.rounded-pill → var(--radius-pill)The class mirrors the token name, so the two always stay in sync..rounded-fullDescribes a scale the tokens never define; the mismatch invites drift.Utilities at work
A handful of structural helpers, read in one glance. This is fair use. The moment the same cluster becomes a card you build twenty times, give it a name and let the helpers go.
<!-- Ticket status: label left, state right, one token gap --> <div class="d-flex items-center justify-between gap-4"> <span class="text-muted text-sm">Ticket status</span> <span class="font-semibold text-success">Confirmed</span> </div> <!-- Long venue name that must never break the row --> <div class="d-flex items-center gap-2 min-w-0"> <span class="truncate">Teatro Metropolitano Jose Gutierrez Gomez</span> </div> <!-- Icon-only button: eyes see the X, screen readers hear the label --> <button class="d-inline-flex items-center focus-ring cursor-pointer"> <span class="sr-only">Close ticket details</span> <svg aria-hidden="true">...</svg> </button>
The two helpers that matter most
Two exist purely to serve assistive technology. Treat them as required infrastructure, not decoration.
| Class | Purpose |
|---|---|
.sr-only | Visually hidden, still announced by screen readers. For icon-button labels, form hints, and status that is obvious by sight but silent to the tree. |
.focus-ring | Applies the system focus treatment on :focus-visible, pairing with var(--color-focus) so keyboard users always see where they are. |
Visually hidden is a solved problem with a canonical recipe. The common shortcut of display: none is wrong for it: that also drops the element from the accessibility tree, the opposite of the goal. This hides the pixels while keeping the text for a screen reader.
Pulls the element out of flow so its collapsed box disturbs nothing around it.
Collapses the box to one pixel. Not zero, since a zero-sized box can be dropped from the tree.
Clips the real content down to that one-pixel box so none of it paints.
Clips the visible region to nothing. The clip-path rule does the work in modern engines; the deprecated clip stays as a fallback.
Stops the collapsed text from wrapping, which could reintroduce a sliver of layout.
Zeroes the box model and nudges it off-screen so nothing leaks, not a border, not a background.
/* The canonical visually-hidden utility */ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.sr-only for meaning that is obvious by sight but silent to the tree, never to stuff invisible keywords.<span class="sr-only">Close</span>Keeps the pixels hidden while the label still reaches assistive tech.display: noneDrops the element from the accessibility tree, so a screen reader never hears it.Which layer, in five questions
When you are unsure which tool to reach for, walk down until one fits.
var(--space-4). No utility needed..sr-only or .focus-ring. Infrastructure, not styling.Sources
Utility-first model and the extract-to-component threshold: Tailwind CSS (tailwindcss.com) and Adam Wathan, CSS Utility Classes and Separation of Concerns (adamwathan.me). The composition-plus-blocks balance follows Andy Bell, CUBE CSS (cube.fyi). The visually-hidden recipe: W3C WAI WCAG technique C7 (w3.org) and Scott O'Hara, Inclusively Hidden (scottohara.me); it ships near-identically as Bootstrap .visually-hidden and Tailwind .sr-only. Visible focus is WCAG 2.1 SC 2.4.7 (w3.org). The exact class names, token bindings, and the reading of .sr-only and .focus-ring as required infrastructure are specific to this system.