Type that scales with the viewport
A size that moves smoothly between two viewports — in rem, so a reader who has enlarged their text still gets larger type.
Type that scales with the viewport
A size that moves smoothly between two viewports, in rem so a reader who has enlarged their text still gets larger type.
The derivation
What it produces at each width
Live preview
Resize this window. The heading below uses the clamp above.
The formula
slope = (yMax − yMin) / (xMax − xMin), intercept = yMin − slope × xMin, and the preferred value is intercept + slope×100vw. clamp() then holds it flat outside the range.
The intercept is emitted in rem by default. A preferred value made only of vw does not respond to the browser's font-size setting at all, so text sized that way cannot be enlarged by a reader who needs it larger. Keeping a rem term is what makes this safe on type.
Both endpoints are checked: the line is asserted to pass through exactly your minimum at the small viewport and exactly your maximum at the large one.
Why not just use media queries?
Breakpoints make type jump. A heading that is 32px at 767px and 44px at 768px is a visible step, and there are always widths in between that neither size suits.
A clamp gives every width its own size, and it is one declaration instead of three.
The zoom problem
This is the part most fluid-type generators get wrong. clamp(1rem, 2.5vw, 2rem) looks fine until a reader zooms: the vw term does not change, so between the bounds the text is effectively pinned. Keeping the intercept in rem means the whole expression scales with their setting.
It is worth testing at 200% zoom, which is what WCAG 1.4.4 requires.