Feature Playground

Mobile / touch · M.3

Fluid type with a checked floor

A thermostat with a minimum setting somebody chose in summer.

clamp() type where the viewport term goes dead below a threshold, so the floor is what actually renders on a phone and nobody ever looked at it.

4 knobs

How it actually works

Fluid type is sold as the thing that makes a layout responsive without breakpoints, and it does, right up until the term that does the fluid part switches off. What is left is a hardcoded size that was never reviewed at the width it applies to. On our own build the floor was wider than the box: a 40px display word measured 330px inside a 272px content box at 320px, which is what tipped the whole site into a shrink-to-fit zoom. One dead term, one unreviewed constant, whole site rendered at 90%.

font-size: clamp(MIN, PREFERRED, MAX) resolves to the preferred value only while it sits between the two bounds. With a vw preferred term there is always a viewport width below which the vw value drops under MIN and the floor takes over: for clamp(2.5rem, 7vw, 4.6rem) that crossover is 40 / 0.07 = 571px, so on every phone in existence the type renders at a flat 40px and the 7vw is decoration. The bug is not the clamp, it is that MIN was chosen by looking at a desktop window, where it never renders.

The knobs, named

Floor, preferred, ceiling, and a viewport-width scrubber. The first three are the three arguments clamp() is defined with, so they are sourced to the CSS spec that names them. The scrubber is ours: it exists so you can watch the crossover happen rather than compute it.

KnobSourceWhat it teaches
Floor (MIN) sourced What actually renders on a phone. This is the number to review, and it is the one nobody looks at because it never shows up on the machine it was chosen on.
Preferred (vw) sourced The fluid term. Divide the floor in px by this over 100 and you get the width below which it is dead. At 7vw with a 40px floor that is 571px, which is every phone.
Ceiling (MAX) sourced The desktop cap. It is the one of the three that gets reviewed most and matters least, because it only binds on a wide window.
Viewport width ours The scrubber. Drag it down and watch the vw term cross under the floor: past that point the headline stops responding and the readout says which term is winning.

sourced means the source names this parameter. ours means the source names none and the knob is our design against the mechanism. No knob here is invented and passed off as sourced.

Evidence

VERIFIED (ours, shipped)

Our own shipped code: clients/harrison-handyman/craft.css, section 3, measured and fixed 2026-07-21. Verbatim from that file: h1 was clamp(2.5rem, 7vw, 4.6rem), "so below ~357px the 7vw term is dead and the floor holds at a flat 40px", the word "set at 40px/900 is 330px wide and the hero's content box at 320px is 272px", and the page shrink-to-fit-zoomed to ~90%. The fix was a narrower clamp under 400px. The three clamp arguments are named by CSS Values and Units Level 4, which is the whole of the sourced claim for those knobs.

Seen on
Our own harrison-handyman build (shipped). Fluid-type advocacy is everywhere; we cite none of it because we took none of it.
Dependencies
vanilla CSS
Difficulty
easy, and the difficulty is entirely in noticing
Performance
None. It is a resolved length.
Accessibility and the floor
clamp() with a rem floor still scales with the reader's own font-size setting, which a vw-only fluid type does not, and that is the real argument for the floor existing at all. Nothing here animates, so the reduced-motion floor is trivially met.
Where our build departs from the source: The stage cannot change the real viewport, so the scrubber changes the width of a SIMULATED viewport box and the vw term is computed against that box rather than read from the browser. Every number shown is the arithmetic the browser would do; the resolved size is applied as a real font-size, so the overflow you see when the floor is too wide for the box is measured, not drawn.

Notes

Composability. It sits underneath every text feature here. The split-text (4.1) and per-word (4.4) stages inherit whatever type scale the page gives them, so a dead floor breaks those too and looks like their bug.

Write the crossover width in the comment next to the clamp. It is one division and it turns an invisible property into a stated one: "below 571px this is a flat 40px" is a claim the next person can check in a second. And check the floor against the narrowest box the type lives in, not against the viewport: 40px fits a 320px screen and does not fit a 272px content box inside it.