Breakpoints and layout

Six breakpoints — Tailwind’s five and one below them — and two layout tokens that step with them. The navigation is outside the layout; the content beside it is not.

The scale

Breakpoints
NamerempxWhat turns there
xs30rem480pxBelow it, a phone: the Toast full width, the CommandPalette’s description under the label, the site’s specimens edge to edge
sm40rem640pxNo reader yet — Tailwind’s step, kept so sm: means the same everywhere
md48rem768pxBelow it, the SideNav is a sheet and the site’s bar is narrow; the Tailwind default, 768
lg64rem1024pxMargin 24 and gap 20 from here; the screen’s navigation leaves its sheet
xl80rem1280pxMargin 40 from here; two panes side by side; the site’s evidence column
2xl96rem1536pxNo component reader; the site’s wide page, with the section list beside the prose

320px is the floor, not a breakpoint: the narrowest width the system is built and tested at, WCAG 1.4.10’s reflow. Every step is in rem, so a reader who sets a larger default font size gets the narrower layout sooner.

Using it

A media query cannot read a custom property, so the tokens reach each place in its own form. In CSS, write the query in rem and range syntax; in React, take it from media; in Tailwind, xs: exists and the other five are Tailwind’s own.

CSS
@media (width < 48rem) { … }   /* below md */
@media (width >= 80rem) { … }  /* xl and up */
TSX
import { media } from 'alpenglow';
const narrow = useMediaQuery(media.down.md); // the app's own hook, or any

--ap-breakpoint-* in tokens.css are for JavaScript and for reading. A test fails on any width in a media query outside the scale.

A layout of your own

Measure where the content breaks, then round to the safe step. This site’s wide page needs 1108 of page between the margins to hold a Table specimen beside the section list — 1500 of viewport, once the rail, the drawer and the margins are out — so it starts at 2xl, 1536; its evidence column needs the prose beside it to keep 704, which it does from xl. The tests hold the inequality, not the number.

The viewport and the container

The viewport decides the chrome and the page’s composition: where the SideNav becomes a sheet, when two panes sit side by side. A component that answers its own space answers its container — the Alert stacks its actions under 400px of its own width in any screen — and a container query is not a breakpoint.

Margin and gap

Layout tokens
TokenNarrow
(below lg, 1024)
Medium
(from lg, 1024)
Wide
(from xl, 1280)
Where
layout/margin16px24px40pxAround the content region: from the navigation’s edge, the window’s edge and the TopBar
layout/gap16px20px20pxBetween panes, and between the columns of a composition

The margin is the space around the content region, from the navigation’s edge, the window’s and the TopBar alike; the TopBar pads its sides by it, so its start and end line up with the content. The gap is between panes and between the columns of a composition. Below xl the content is one pane, two behind Tabs; from xl two sit side by side. There is no 12-column grid in code: the Scheduler and the Table size themselves. In Figma the Alpenglow Layout collection has the three modes, and a 12-column grid style is bound to it as a guide. The package’s default keeps the SideNav a rail down to md; beside a Scheduler, pass it narrow={media.down.lg} instead, so a tablet gets the whole 736 rather than sharing it with the rail.

Narrow — margin 16, gap 16
Medium — margin 24, gap 20
Wide — margin 40, gap 20

Layering

Alpenglow ships no z-index tokens. What floats goes to the top layer; what stacks inside a component stays in its own isolation: isolate, at 3 or under. The page’s stack is the product’s: a sticky bar at z-index: 1 sits over everything the package draws.

Not checked

Safari, Firefox, a real touch device, and text zoom beyond the browser’s default font size.