demo · v138
Typography scale test bench
Eight type-scale steps, a side-by-side card comparison, and a manual override slider to simulate the OS preference if your platform doesn't expose it yet. env(preferred-text-scale) defaults to 1 when the OS doesn't have an opinion — so this is one of those rare features where the right CSS is also the right fallback.
Type ramp · all sizes × env(preferred-text-scale)
Cards: text only vs everything scaled
card-text-only — only font sizes scale
Cache sharing
Allow-listed pervasive resources can share cache across origins. Smaller downloads, no correctness regressions.
card-everything — padding, icon, button all scale with --xc
Cache sharing
Allow-listed pervasive resources can share cache across origins. Smaller downloads, no correctness regressions.
At 1.8×: the left card has cramped hit-targets — text is huge, button is the same. The right card keeps the entire layout proportional. The "proportional chrome" pattern is the practical thing to ship.
The CSS
:root {
--tx: env(preferred-text-scale, 1); /* defaults to 1 when OS doesn't expose */
}
h1 { font-size: calc(2.2rem * var(--tx)); }
body { font-size: calc(1rem * var(--tx)); }
/* the proportional-chrome trick: multiply hit-targets and padding by the same factor */
button {
padding: calc(0.55rem * var(--tx)) calc(0.9rem * var(--tx));
font-size: calc(0.9rem * var(--tx));
}
.icon { width: calc(24px * var(--tx)); height: calc(24px * var(--tx)); }
What's happening
env(preferred-text-scale, fallback)resolves to the user's OS-level font scale, or the fallback if unsupported / no opinion.- Multiplying every font size by this single factor gives a site-wide ramp that respects accessibility without any media query rewriting.
- Multiplying everything — paddings, hit targets, icons — by the same factor gives "proportional chrome", which keeps the layout touch-friendly at large scales.
- Default value
1means existing code paths are unchanged. This is one of the few APIs where adopting it costs nothing.