TLDR: Never set
font-sizeonhtml.cqion the root element resolves against the viewport, not a container — and it will silently detonate everyrem-based clamp downstream.
What I Was Building
A marketing client's workshop site needed to do two things at once.
Live: fill a 16:9 projector at a client offsite.
Later: read as a permanent leave-behind on a laptop.
Same URL. Same HTML. Both had to look right.
The trick I reached for was container queries. I gave each slide panel a fixed .inner element — width: min(96vw, calc(94vh * 16/9)) with aspect-ratio: 16/9 and container-type: inline-size. Every font size and spacing token inside was written in cqi units (container query inline-size), so they scaled with the stage, not the viewport. A 16:9 screen and a 16:10 laptop both got a 1760×990 stage, letterboxed in its own panel background. GENIUS, I thought.
Then the slides started breaking.
What Broke
Dense slides overflowed the stage by 100–200px.
Cards rendered far too tall. Body text was massive. H2 headlines wrapped when they shouldn't.
The overall read: "still broken in multiple places."
What I Tried
I started pulling on the obvious threads.
- Tightened heading font sizes
- Shrunk card padding
- Reduced gallery card count from 6 to 4
- Adjusted the type scale on individual panels
Twelve commits. All symptoms. None of them stuck.
(I'll be honest — I was in the weeds. I was treating a patient with a fever by adjusting their thermostat.)
The Fix That Worked
I measured.
Arc CDP (Chrome DevTools Protocol — a way to query the live browser's computed styles from a script) let me read the actual computed font-size on html...
36px.
The default is 16px. I had it at 36px.
Here's the line that did it:
html, body {
font-size: var(--body); /* --body: clamp(0.95rem, 1.7cqi, 2.25rem) */
}
The problem: cqi on html has no container ancestor to resolve against, so it falls back to the viewport. On a 2540px-wide screen: 1.7% × 2540 = 43px. The clamp caps at 2.25rem... which against a 36px root is 81px. But even at cap it returned 36px and set root font-size there.
Every rem-based clamp min downstream now scaled against 36px instead of 16px. So clamp(0.85rem, 1.3cqi, 1.7rem) — meant to have a 13px floor — had a 30px floor. The min won. Every responsive mid-range was defeated before it started.
The fix was one line. Move font-size off html, put it on body only:
html { /* no font-size here — ever */ }
body { font-size: var(--body); }
body has a container ancestor (html). cqi resolves normally. Every clamp snapped back into range. Every slide fit.
Why This Matters to Me
Twelve commits of trimming individual rules. One line was wrong, upstream, invisible because I never measured it.
The lesson I codified and saved: when N things look broken, suspect ONE root cause. Measure before you trim. And specifically — cqi on html is viewport-relative. It will always be. That's the spec. Put font-size on body, never html, and you never hit this again.
P.S. The 16:9 stage pattern — the full CSS — is now living in a reference memory file. If you're building a presentation site that has to dual-serve projector + web, the pattern is battle-tested.