Utilities
Single-purpose classes
Utilities handle the cases that don't earn their own component or
token override: set text alignment on one element, nudge a gap to a
specific size, hide something on mobile. Each utility does exactly
one thing. They live in the utilities cascade layer,
so they win over lower layers without !important.
Brio is not a utility framework. The catalog below is deliberately narrow and will stay that way: if you find yourself wanting more, first check whether a token override, composition primitive, or component handles it. Only reach for a utility when those don't.
The class tables below are pulled from src/css/utilities.css
via brio cssref, so they stay in sync with the source.
The two single-utility sections (.visually-hidden and
.link-plain) are described in prose because their
behavior doesn't fit a one-line table cell.
Visibility
-
.visually-hidden-- hide from the visual UI while remaining in the accessibility tree. Use for skip links, form labels that the design doesn't show, and screen-reader-only text. Not the same as[hidden](which removes the element from the a11y tree too).
Text
Alignment
Logical-property values so RTL writing modes flip correctly.
| Class | Description |
|---|---|
.text-start | Align text to the inline-start edge |
.text-center | Center text |
.text-end | Align text to the inline-end edge |
Color
Maps to semantic color tokens. Keep these minimal; component-scoped tokens are usually the right override point instead.
| Class | Description |
|---|---|
.text-muted | Muted secondary text |
.text-subtle | Subtle de-emphasized text |
.text-inverse | Inverted text for dark surfaces |
.text-primary | Primary brand color |
.text-normal | Reverts to the default --color-text |
.text-accent | Accent color |
.text-success | Success status color |
.text-warning | Warning status color |
.text-danger | Danger status color |
Family and case
| Class | Description |
|---|---|
.text-mono | Switch to the monospace family |
.text-uppercase | Transform to uppercase |
.text-lowercase | Transform to lowercase |
Size
Keyed to the fluid type scale. See the type scale on the Tokens page for the resolved sizes at each breakpoint.
| Class | Description |
|---|---|
.text--2 | Smallest caption size |
.text--1 | Step below body |
.text-0 | Body baseline |
.text-1 | One step above body |
.text-2 | Subheading |
.text-3 | Heading |
.text-4 | Large heading |
.text-5 | Display size |
See Tokens -- Type scale for the resolved sizes at each breakpoint.
Weight
| Class | Description |
|---|---|
.text-thin | Thin (100) |
.text-extralight | Extra light (200) |
.text-light | Light (300) |
.text-normal | Normal (400) |
.text-medium | Medium (500) |
.text-semibold | Semibold (600) |
.text-bold | Bold (700) |
.text-black | Black (900) |
Line height
| Class | Description |
|---|---|
.leading-tight | Tight leading for labels |
.leading-heading | Default heading leading |
.leading-body | Default body leading |
.leading-loose | Loose leading for emphasis contexts |
Links
-
.link-plain-- remove underline and use--color-text. For logo links, breadcrumb home, and similar cases where the anchor is chrome rather than prose.
Spacing
Gap
Set the gap property directly, keyed to the raw --space-* scale. Use when you want an explicit size on a flex or grid container.
| Class | Description |
|---|---|
.gap-3xs | gap: var(--space-3xs) |
.gap-2xs | gap: var(--space-2xs) |
.gap-xs | gap: var(--space-xs) |
.gap-sm | gap: var(--space-sm) |
.gap-md | gap: var(--space-md) |
.gap-lg | gap: var(--space-lg) |
.gap-xl | gap: var(--space-xl) |
.gap-2xl | gap: var(--space-2xl) |
For density-aligned gaps (inside .stack,
.cluster, or a component), prefer the .is-snug
/ .is-tight modifiers the composition primitive provides,
or override --stack-gap / --cluster-gap
with a --gap-* alias from the density grammar. The raw
.gap-* utilities are for deliberate one-off sizing.
Flow space
Set --flow-space at the --space-* scale. Apply to a .flow container to set its rhythm, or to an individual child to tune the gap above just that element.
| Class | Description |
|---|---|
.flow-space-none | --flow-space: 0 |
.flow-space-3xs | --flow-space: var(--space-3xs) |
.flow-space-2xs | --flow-space: var(--space-2xs) |
.flow-space-xs | --flow-space: var(--space-xs) |
.flow-space-sm | --flow-space: var(--space-sm) |
.flow-space-md | --flow-space: var(--space-md) |
.flow-space-lg | --flow-space: var(--space-lg) |
.flow-space-xl | --flow-space: var(--space-xl) |
.flow-space-2xl | --flow-space: var(--space-2xl) |
.flow-space-3xl | --flow-space: var(--space-3xl) |
Apply .flow-space-* to a .flow container
to set its rhythm, or to an individual child to tune the gap above
just that element (see the Flow
per-child override pattern).
Responsive visibility
Viewport
Hide elements based on viewport width. Breakpoints: sm 40rem, md 48rem, lg 64rem.
| Class | Description |
|---|---|
.hide-below-sm | Hidden below the sm breakpoint |
.hide-below-md | Hidden below the md breakpoint |
.hide-below-lg | Hidden below the lg breakpoint |
.hide-above-sm | Hidden at the sm breakpoint and above |
.hide-above-md | Hidden at the md breakpoint and above |
.hide-above-lg | Hidden at the lg breakpoint and above |
Breakpoints match the breakpoints
reference. Pair them for mobile-swap-desktop patterns:
.hide-above-md on the hamburger button,
.hide-below-md on the nav. The hamburger shows below
the breakpoint; the nav shows at and above.
Container queries
Opt a parent into container queries with .cq-inline, then use .cq-hide-* on its descendants to respond to the container's inline size instead of the viewport.
| Class | Description |
|---|---|
.cq-inline | Opt into inline-size container queries |
.cq-hide-below-sm | Hidden when the container is below sm |
.cq-hide-below-md | Hidden when the container is below md |
.cq-hide-below-lg | Hidden when the container is below lg |
.cq-hide-above-sm | Hidden when the container is sm or wider |
.cq-hide-above-md | Hidden when the container is md or wider |
.cq-hide-above-lg | Hidden when the container is lg or wider |
Use container queries when you want responsive behavior based on a container's width instead of the viewport -- useful for widgets that appear in contexts of varying width (sidebar vs main, card grid vs full width, etc.).
Drag the right edge to cross the md breakpoint and see the utilities swap:
This is a query container.
<docs-resize>
<div class="cq-inline">
<p>This is a query container.</p>
<p class="cq-hide-below-md text-success">I hide when the container is under 48rem (md).</p>
<p class="cq-hide-above-md text-danger">I hide when the container is 48rem or wider.</p>
</div>
</docs-resize>
Container-query breakpoints match the viewport breakpoints so the
vocabulary stays consistent. The difference is what the breakpoint
resolves against -- the container's width for .cq-*,
the viewport for .hide-*.