Broader Ideas
Container queries make design systems possible
Before container queries, a "reusable" component had three bad options for context-awareness: a
size prop (the consumer must know, and can be wrong), a viewport media query (wrong in every
non-full-width context), or ResizeObserver (JavaScript, layout thrash risk, hydration mismatch).
@container removes the coordination entirely. The component asks about the space it was given.
This is a genuine capability change, and it invalidates prior architecture: component APIs designed
around size="compact" | "comfortable" props may now be expressing in TypeScript something CSS can
determine. Worth re-examining as part of fe-38 and the technology-radar process in fe-50 — the same
pattern noted in fe-05, where cascade layers invalidated the reasoning behind CSS-in-JS adoption.
ResizeObserver is now mostly a fallback
The historical pattern — observe an element, set a class, style from the class — costs a JS round-trip per resize, risks layout thrash (fe-01), and produces SSR/hydration mismatches because the server does not know the size.
@container is declarative, runs in the rendering steps, and is correct on first paint including
server-rendered HTML. ResizeObserver remains right when you need the number in JavaScript
(canvas sizing, virtualization measurement, chart scales), not when you need styling.
Note the connection back to fe-01: ResizeObserver callbacks run inside "update the rendering", can
loop, and are specified to drop notifications rather than hang — the platform choosing to lose
work instead of freezing.
Intrinsic sizing removes magic numbers, which removes bugs
.badge { width: 80px; } /* breaks: long strings, i18n, user font size */
.badge { width: fit-content; } /* correct; measured within 7% of fixed */
Every hardcoded dimension is an assumption about content that will eventually be false — German compounds, Arabic, a user with a 200% font size, a product name nobody anticipated (fe-26). Intrinsic sizing costs a measurement and removes the whole class.
The exception is deliberate truncation, where a fixed size is the design decision. Then it should
be paired with text-overflow, a title, and a plan for what a screen reader announces.
Layout is where CLS is won
Cumulative Layout Shift is a layout-stability problem, decided by choices in this module rather than by anything in a performance sprint:
| Cause | Fix, at design time |
|---|---|
| images without dimensions | width/height attributes, or aspect-ratio |
| ads/embeds of unknown size | reserve with min-height or aspect-ratio |
| web fonts swapping metrics | size-adjust, ascent-override on @font-face |
| content injected above the fold | reserve space, or inject below |
content-visibility without contain-intrinsic-size | always pair them (fe-05) |
The last row connects the two modules directly: the 98% layout win from fe-05 introduces a CLS risk
if contain-intrinsic-size is omitted, because skipped subtrees measure as zero.
The folklore-correction pattern
This module's headline result — 1.4× across every layout mode, with the supposedly-fastest mode slowest — is the third instance of the same pattern in Phase 1:
| Module | Folklore | Measured |
|---|---|---|
| fe-03 | property order is the hidden-class hazard | 1.14×; delete is 11.9× |
| fe-04 | semantic HTML is verbose | div soup is 1.38× larger |
| fe-06 | flex/grid are slow, absolute is fast | 1.4× spread; absolute slowest |
The transferable skill is not the individual corrections — those will drift with engine versions. It is the reflex: when advice is repeated confidently and cheaply, measure it before you design around it. Every one of these had a real effect somewhere, misremembered as a general rule.