--- title: "Classes" subtitle: "The utility layer, and what each class is allowed to do" description: "The general-purpose utility classes: text size and colour, spacing, containers, layout primitives and helpers, with the token each one resolves through." author: "Studio" section: "Website" subsection: "Foundations" order: 4 status: "published" --- Utilities apply a token to an element without writing CSS. Most modify a single concern — a size, a colour, a gap — so they compose rather than compete, and none of them carries a raw value of its own. A few set a pair that always travels together: the text-size classes set line height alongside font size, and `.label` and `.eyebrow` set a whole small type treatment. Where a class resolves through a token, the token's value is on the [Tokens](/website/tokens.html) page. ## Text size The two spellings are aliases of one rule, not two scales: `.text-size-l` and `.text-size-large` are the same declaration. Use whichever reads better and stay consistent within a page. | Class | Alias | Resolves to | Value | | --- | --- | --- | --- | | `.text-size-xl` | `.text-size-xlarge` | `var(--text-size-xl)` | 28px, stepping to 24px below 960px | | `.text-size-l` | `.text-size-large` | `var(--text-size-l)` | 20px | | `.text-size-m` | `.text-size-medium` | `var(--text-size-m)` | 16px — body size | | `.text-size-s` | `.text-size-small` | `var(--text-size-s)` | 14px | | `.text-size-xs` | `.text-size-xsmall` | `var(--text-size-xs)` | 14px |

.text-size-xl

Where Culture Meets Care

.text-size-l

Where Culture Meets Care

.text-size-m — body

Where Culture Meets Care

.text-size-s

Where Culture Meets Care

.text-size-xs — identical to small today

Where Culture Meets Care

- **Do not reach for `.text-size-xs` expecting something smaller than small.** Both steps resolve to 14px today, so the two are visually identical; the distinction exists in the token layer, not on screen. ## Font size The text-size classes above are the default. These apply a step of the primitive scale directly, for the cases where the semantic scale has no rung in the right place. | Class | Value | Class | Value | | --- | --- | --- | --- | | `.font-2xs` | 12px | `.font-4xl` | 32px | | `.font-xs` | 14px | `.font-5xl` | 36px | | `.font-s` | 16px | `.font-6xl` | 40px | | `.font-m` | 18px | `.font-7xl` | 48px | | `.font-l` | 20px | `.font-8xl` | 56px | | `.font-xl` | 22px | `.font-9xl` | 64px | | `.font-2xl` | 24px | `.font-10xl` | 72px | | `.font-3xl` | 28px | | | `--font-3xs` (10px) exists as a token but ships no utility. Two family classes sit alongside these: `.font-primary` sets Inter and `.font-secondary` sets Erode. - **Prefer the semantic scale.** `.text-size-m` keeps following the system if the body size is ever re-stepped; `.font-s` is pinned to 16px whatever happens around it. ## Text colour | Class | Token | | --- | --- | | `.text-primary` | `var(--text-primary)` | | `.text-secondary` | `var(--text-secondary)` | | `.text-faded` | `var(--text-faded)` | | `.text-accent` | `var(--text-accent)` | | `.text-plain` | `var(--text-plain)` | | `.text-link` | `var(--text-link)` | What each token means and its value in both themes are on the [Colour](/website/color.html) page; this table is only the mapping from class to token. ## Background | Class | Token | | --- | --- | | `.bg-primary` | `var(--background-primary)` | | `.bg-secondary` | `var(--background-secondary)` | | `.bg-plain` | `var(--background-plain)` | | `.bg-faded` | `var(--background-faded)` | ## Text alignment `.text-left` · `.text-center` · `.text-right` ## Section spacing `.top-small` · `.top-medium` · `.top-large` · `.top-xl` and the matching `.bottom-*` set the vertical space between bands of a page. The values and the token chain behind them are on the [Spacing](/website/spacing.html) page. ## Gap Micro spacing inside a block, and the only source of vertical rhythm there — the [Spacing](/website/spacing.html) page explains why a margin cannot be used instead. | Class | Value | Class | Value | | --- | --- | --- | --- | | `.gap-none` | 0 — but see below | `.gap-l` | 16px | | `.gap-xs` | 4px | `.gap-xl` | 24px | | `.gap-s` | 8px | `.gap-2xl` | 32px | | `.gap-m` | 12px — the default | `.gap-3xl` | 40px | - **`.gap-none` does not work on a `.grid`.** It is the only gap utility without `!important`, and `.grid` sets its own 12px gap later in the stylesheet at equal specificity, so `class="grid gap-none"` still renders 12px. On a `.block` it behaves as written. ## Padding | Class | Value | Class | Value | | --- | --- | --- | --- | | `.padding-s` | 8px | `.padding-xl` | 24px | | `.padding-m` | 12px | `.padding-2xl` | 32px | | `.padding-l` | 16px | `.padding-3xl` | 40px | `.padding-global` sets the horizontal page gutter at 24px on both sides, and is the class that keeps every section's content aligned to the same edge. ## Containers and max-widths `.container-xs` through `.container-xl` cap width and centre; `.max-width-xs` through `.max-width-xl` cap width and leave the element where it is. `.max-width-full` releases a constraint set further up. The five widths and what each suits are on the [Layout](/website/layout.html) page. ## Layout primitives | Class | What it does | | --- | --- | | `.block` | A flex column with a 12px gap. The workhorse — almost every stack of content is one | | `.grid` | A grid, two columns by default, with a 12px gap | | `.cols-2` · `.cols-3` · `.cols-4` | Column count on a grid | | `.row` · `.row-reverse` | Lays a block out horizontally instead | ## Alignment modifiers `.align-start` · `.align-center` · `.align-end` · `.align-stretch` set cross-axis alignment; `.justify-center` and `.justify-end` set main-axis. `[data-align="center"]` centres a block itself rather than its contents. ## Helpers | Class | What it does | | --- | --- | | `.eyebrow` | The small tracked label above a heading | | `.label` | A form or metadata label | | `.fit-content` | Shrinks an element to its content width | | `.visually-hidden` | Removes an element visually while leaving it in the accessibility tree — the correct way to label an icon-only control | | `.is-hidden` | Removes it from both | | `.overflow-hidden` | Clips overflowing children | ## Elsewhere | Utilities | Documented on | | --- | --- | | `.border`, `.border-*` — position, width, style and colour | [Border](/website/border.html) | | `.img`, `.img-1x1` and the other aspect ratios | [Image](/website/image.html) | ## Rules - **Never mix layout responsibilities.** Sections carry macro spacing with `.top-*` and `.bottom-*`, blocks carry micro spacing with `.gap-*`, and containers carry width. A container that sets its own padding has taken on a job that is not its own. - **Never put a margin inside a block.** Gap is the single source of spacing there, and a margin adds to it rather than collapsing with it. - **Ignore `.padding-section`.** It ships as `display: block` and applies no padding at all, despite the name; section spacing comes from `.top-*` and `.bottom-*`. - **Never write a utility that carries a literal value.** If a class needs a value the tokens do not cover, the token scale is missing a step — add the step.