Skip to content
FoundationsBreakpoints

Breakpoints

Six canonical breakpoints. Mobile-first naming, min-width semantics — every breakpoint is the size above which the layout shifts. Below xs, treat the layout as "narrowest viable mobile."

TokenMin widthTypical surfaceLayout shift at this breakpoint
xs360pxNarrow phonesFooter columns stack to one
sm640pxLarge phones, small tabletsDashboard sidebar collapses to drawer
md768pxTablets, split-screen laptopsTwo-column body grids appear
lg1024pxStandard laptopsThree-column grids appear; rails activate
xl1280pxWide laptopsContent max-width caps; lateral padding grows
2xl1536pxMonitors, large desktopsHero typography max-scale; no further shifts

Reading the tokens

import { breakpoints } from "@matter/tokens";

breakpoints.md; // "768px"

In CSS:

@media (min-width: 768px) {
  /* md and up */
}

/* or use the variable — same value, theme-agnostic */
@media (min-width: var(--breakpoint-md)) {
  /* md and up */
}

In Tailwind (the @matter/presets-tailwind preset maps each token to a screen):

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">

</div>

Container queries first

For component-level responsive behaviour, prefer container queries over breakpoints:

.card-grid {
  container-type: inline-size;
}

@container (min-width: 640px) {
  .card-grid__item {
    /* card-grid is 640px wide or more — column up */
  }
}

Container queries scope to the component's parent, so a card grid inside a sidebar reflows independently from a card grid in the main column. Breakpoints scope to the viewport — reach for them only when the page-level shell itself shifts.

Why six, not five or seven

  • xs anchors the "narrowest viable" surface — below 360px, design fidelity drops and we don't optimise.
  • sm / md cover the phone-to-tablet transition where most dashboard surfaces change shape.
  • lg is where rails appear — most product layouts assume lg and up for the canonical layout.
  • xl is where content caps stop growing. Beyond this, we add lateral padding, not column count.
  • 2xl is the cap for hero typography. Beyond this, large monitors get whitespace, not larger text.

A seventh breakpoint (3xl at 1920px+) was considered and rejected — wide monitors get whitespace, not more columns, and 2xl is enough to cap hero typography.

Compact-density interaction

The site's density toggle is orthogonal to breakpoints. Density adjusts vertical rhythm and touch-target padding; breakpoints adjust column count and rail visibility. A user on lg with compact density gets the 3-column dashboard with tighter row padding — both axes are independent.

Touch-target floor

At every breakpoint, interactive touch targets stay ≥ 44×44 px (WIG touch rule). Density compaction never violates this floor. Compact density tightens spacing around touch targets, not the targets themselves.

What's in scope

In scope (system owns)Out of scope (consumer owns)
The six breakpoint valuesPer-page custom breakpoints
--breakpoint-{tier} CSS variablesApp-specific media queries
Tailwind preset mappingComponent-level container queries

What's deliberately not here

  • Print breakpoints. Print styles live in @matter/tokens/css/print as a separate stylesheet; the six tiers above don't apply to print.
  • Orientation-based queries. @media (orientation: portrait) is consumer responsibility — no canonical token surface.
  • Hover-capable detection. @media (hover: hover) is consumer responsibility for context-specific affordances.

On this page