4 columns · the base
03 / Layout primitives
Seven primitives. Almost no breakpoints.
Every demo below is live — drag the window narrower and watch. Nothing here uses a media query. fr distributes leftover space, minmax and clamp set the boundaries, and the browser resolves the rest. Breakpoints only appear where a layout must genuinely change shape rather than reflow.
Specified, not built. The layout tokens ship — --se-container-max, the breakpoints, the grid columns and gutters, --se-col-min, --se-sidebar-min. The seven primitives below do not. The demos are real CSS you can copy; they are not something the package exports yet.
Column grid — 4 / 8 / 12
Page composition starts at four columns and doubles, then adds half again: four on phones, eight on tablets, twelve on desktop. Four is the right floor because it is the smallest count that still divides usefully — halves and quarters — and because eight columns on a 375px screen gives you 30px tracks that no content fits into.
--se-grid-columns: 4;
--se-grid-gutter: var(--se-space-4);
--se-grid-margin: clamp(1rem, 4vi, 2rem);
[data-se-layout="grid"] {
display: grid;
grid-template-columns: repeat(var(--se-grid-columns), minmax(0, 1fr));
gap: var(--se-grid-gutter);
padding-inline: var(--se-grid-margin);
}
@media (--se-bp-md) { :root { --se-grid-columns: 8; } }
@media (--se-bp-lg) { :root { --se-grid-columns: 12; } }
Two media queries, and they are the only ones in the system. Worth being honest about why they earn an exception: a column count is a discrete decision, not a continuous one. There is no such thing as 7.4 columns, so no amount of clamp or fr can interpolate between four and eight. Everything the column grid holds still sizes itself intrinsically — the grid decides where things sit, never how big they are. Component-level layout uses the intrinsic primitives below and needs no breakpoints at all.
Container — a measurement scope, not a placement
The fluid tokens measure cqi, which resolves against the nearest container and falls back to the viewport when there is none. data-se-container is the opt-in: written on a panel, a card column or an inspector, the type and rhythm inside it answer to its width instead of the window's. A page that never writes it reads exactly as before.
[data-se-container] { container-type: inline-size; }
[data-se-container="size"] { container-type: size; } /* rare: also wants cqb; must have a bound block size */
<aside data-se-container class="inspector">
<h3 data-se-text="heading">Sized to the panel, not the page</h3>
</aside>
This one ships — it is two rules in the package CSS, and the tokens depend on it being available. Unlike the primitives it places nothing; declaring a container also means the region's own inline size can no longer come from its contents, which is why it is an opt-in rather than something every card does by default.