How Do You Build a Fluid Type Scale That Passes WCAG?
How Do You Build a Type Scale That Works at Every Screen Size?
Define each text size once as a range rather than as a set of fixed values per breakpoint. One CSS function handles the interpolation, so a heading grows smoothly from phone to desktop instead of jumping at four arbitrary widths. The catch is an accessibility rule most fluid type gets wrong.
We moved our Webflow builds to this approach because the breakpoint version never stopped costing us time. Every new text style meant four values, and every design tweak meant four edits, and one of them was always missed.
This walkthrough covers the mechanics, the accessibility constraint that decides your numbers, and how we keep the scale maintainable inside a Designer driven project.
What Is Fluid Typography, and Why Not Just Use Breakpoints?
Fluid typography sets a size that scales continuously with the viewport, between a floor and a ceiling. Breakpoint typography sets fixed sizes that change in steps. The fluid version has fewer values to maintain and no awkward widths where the type is wrong.
The awkward widths are the real argument. With breakpoints, a heading sized for a phone and a heading sized for a tablet meet somewhere around 700 pixels wide, and at that exact width one of them looks wrong. Nobody designs for 712 pixels, but plenty of people browse at it.
Breakpoints are still right for layout. A two column grid becoming one column is a genuine step change, not an interpolation. Our piece on responsive breakpoints covers where the steps still belong.
Type is different because it has no natural steps. A heading does not need to be 32 pixels or 48 pixels. It needs to be proportionate to the space it sits in, and that space changes continuously.
How Does clamp() Actually Work?
It takes three values and picks the middle one unless it falls outside the bounds. MDN describes it as clamping "a value within a range of values between a defined minimum bound and a maximum bound," with the arguments in the order minimum, preferred, maximum.
The resolution rule is worth memorising because it removes the guesswork. MDN states that the function resolves as the maximum of the minimum and the smaller of the preferred and the maximum. In plain terms, the preferred value is capped at the maximum first, then floored at the minimum.
So a declaration reading clamp(1rem, 2.5vw, 2rem) means the text is 2.5 percent of the viewport width, never smaller than 1rem, never larger than 2rem. Three numbers, one line, every screen size handled.
Support is not a concern. MDN lists the function as Baseline "Widely available," noting it "has been available across browsers since July 2020." This is settled technology, not something to feature detect.
What Is the Accessibility Trap in Fluid Type?
Viewport units do not respond to browser zoom the way people expect. If a font size depends only on viewport width, zooming can fail to enlarge the text, because the viewport width in CSS pixels changes as you zoom. Text that cannot grow is an accessibility failure, not a style choice.
MDN gives the fix as a hard rule, and it is the most important sentence in this article. When using the function for font sizes with viewport relative units, "ensure that the maximum allowed value is a relative length unit that is no less than twice the minimum allowed value."
That is why clamp(1rem, 2.5vw, 2rem) is the example MDN uses. The maximum is a relative unit, and it is exactly twice the minimum. MDN's own note explains the purpose: it "ensures text size can scale to at least 200% if the page is zoomed."
The consequence for your scale is concrete. Every step's maximum must be at least double its minimum, and both must be relative units. A maximum expressed in pixels breaks the rule no matter how large it is.
What Does WCAG Actually Require?
Success Criterion 1.4.4 Resize Text, at Level AA, states that "except for captions and images of text, text can be resized without assistive technology up to 200 percent without loss of content or functionality." That is the standard your numbers have to satisfy.
Two things in that wording matter. The figure is 200 percent, which is where MDN's doubling rule comes from. And the requirement is not only that the text gets bigger, but that nothing is lost when it does.
The documented failures make the second half concrete. The WCAG understanding document names F69, the failure "when resizing visually rendered text up to 200 percent causes the text, image or controls to be clipped, truncated or obscured," and F80, which applies when "text-based form controls do not resize when visually rendered text is resized up to 200%."
So a fluid scale that doubles correctly but pushes a heading out of its container at 200 percent zoom still fails. The type scale and the layout have to survive the zoom together, which is why we test the two at once. Our piece on building a style guide page in Webflow covers where we do that testing.
How Many Sizes Should a Scale Have?
Six or seven, including body text. Fewer and designers start inventing one offs. More and nobody can remember which step to use, so they pick by eye and the scale stops being a system.
Here is the shape we start from. Every maximum is at least twice its minimum and both are relative units, which keeps the whole scale compliant by construction rather than by later checking.
| Step | Minimum | Preferred | Maximum |
|---|---|---|---|
| Display | 2rem | 5vw | 4rem |
| Heading 1 | 1.75rem | 4vw | 3.5rem |
| Heading 2 | 1.5rem | 3vw | 3rem |
| Heading 3 | 1.25rem | 2.25vw | 2.5rem |
| Body large | 1.125rem | 1.5vw | 2.25rem |
| Body | 1rem | 1.15vw | 2rem |
| Small | 0.875rem | 1vw | 1.75rem |
Treat those numbers as a starting point to tune against your typeface, not as a formula. A tall x-height face needs smaller values than a small one at the same apparent size. Our piece on web typography and font choices covers picking the face first.
Where Should the Scale Live in a Webflow Project?
In one place, declared once, referenced everywhere. The failure mode in a Designer driven project is not the CSS. It is the same size being typed into fifteen different text styles, so a change to the scale becomes fifteen edits and one of them gets missed.
Our approach is to keep the scale definition in a single custom CSS block, and to give every text style a class that inherits from it rather than carrying its own value. Then changing the display size is one edit in one place, and the site updates everywhere.
Build a page that renders every step in the scale as well, with real copy rather than placeholder text. That page is where you check the scale, where a new designer learns it, and where you test zoom behaviour before launch.
Resist per section overrides. The moment a section gets a hand tuned heading size, the scale has an exception, and exceptions multiply. If a section genuinely needs a different size, that is a missing step in the scale, so add it properly.
What About Line Height and Line Length?
Both need to change with the size, and neither should be fluid in the same way. Line height works best as a unitless multiplier, so it scales automatically. Line length is a layout constraint, and it wants a maximum width rather than a viewport formula.
Larger text wants a tighter multiplier. A display heading at a body text line height looks loose and airy in a way that reads as unfinished. Smaller text wants the opposite, because long lines of small type are hard to track back.
For line length, cap the measure on your text containers. Fluid type on a full width container produces lines that are technically the right size and genuinely hard to read on a wide monitor. The size was never the problem there.
How Do You Test It Properly?
Resize the browser slowly and watch for the moment something looks wrong, then zoom to 200 percent and check nothing is clipped. Both tests, every time. The first catches the scale, the second catches the WCAG requirement.
Do the zoom test on a real page with a real navigation bar and a real form, not on your style guide page. The failures WCAG documents are about clipping and form controls, and neither appears on a page that only contains headings.
Check the narrow end too. At the phone width your minimum values apply, so the fluid part of the formula is doing nothing and the scale is effectively fixed. If the hierarchy collapses there, the minimums are too close together.
One last check that catches a surprising number of problems. Set the browser's default font size larger than normal and reload. Text sized in relative units responds, and anything you accidentally left in pixels does not.
What Would We Do on Your Site First?
Count the distinct font sizes currently in use. Most sites we inherit have between twenty and forty, and the first job is not to make them fluid. It is to decide which seven you actually want.
Then check the zoom behaviour of what you have before changing anything. If text already fails to reach 200 percent, that is a live accessibility problem and it is worth fixing on its own, independently of any redesign.
If you want help building a type system that holds up across a whole site rather than looking right on the home page, we are happy to take a look with you. You can find us at phoenix.studio.
Want a site that performs like this?
Tell us about your project. We will come back with a clear next step, no pressure.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
Have a project like this?
Tell us where you want to go. We'll tell you how we'd get you there.