Breakpoints should key off the container, not only the viewport
Aliases: container query breakpoint · slot width not viewport · element query layout
What it is
Where a component changes layout should follow how wide the slot it was given is, not only how wide the browser window is. Viewport queries assume the piece spans the window. Dashboards, split panes, cards in a sidebar, embedded widgets: the window can be wide and the slot narrow. The same card can run multi-column in the main pane and single-column in the sidebar, in one viewport.
Viewport breakpoints belong on the shell (page nav, full-bleed hero). A slotted component bound to the viewport will use a “desktop” layout inside a narrow slot on a wide window, or a “phone” layout inside a wide slot on a narrow window.
Why it happens
@media reads the viewport. What the component can actually use is the width its parent allocated. Those match only when the component happens to span the window. Columns, grids, draggable splitters, and embeds make them diverge: a desktop viewport can give the sidebar 280px and the main pane 900px. A card keyed to the viewport still lays out as if it had 900px while sitting in the sidebar, and overflows or shrinks controls below a usable size.
Keying the breakpoint to container width lets the same card rules fire in the sidebar and the main pane without the window changing first. The window stays put, the slot changes (splitter drag, shell from one column to two), and layout follows. What is being responded to is available width, not a device name, and not “does this look like a phone.”
Where it stops holding
Shell that truly spans the window — full-width nav, a full-bleed campaign head, a page-sized canvas — has the viewport as its container; a viewport query is correct. Mail, some WebViews, and older engines without container queries fall back to viewport as an environment limit, not a design preference; those environments should not drop the same component into wildly different slots. A native window treats window width as the container; that is not “another viewport wrapped around it.” Print’s container is the page, not the screen viewport. A very thin decorative rail (icon strip) should not reuse a content-card’s container breakpoints; those were written for a readable content slot.
Applying it
- Mark components that appear in more than one slot width (cards, filter bars, table toolbars) and give them slot-width shifts instead of copying page-level viewport bands.
- The page shell may still use the viewport; do not copy those bands into every child.
- Draw “wide window + narrow slot” and “wide window + wide slot” in the design, not only device-framed artboards.
- How to check: hold a desktop viewport fixed and place the same component in the sidebar and the main pane. The two layouts should split by slot width. If both look computed from one viewport band, the breakpoint is still bound to the window.