Fluid Typography with Clamp(): A Practical Tutorial
A step-by-step tutorial on building a fluid type scale with clamp(), with worked examples and a link to the FontBlend fluid type generator.
Fluid typography uses the CSS clamp() function to scale font sizes smoothly between a minimum and a maximum, based on the viewport width. The result is text that is readable on a 360px phone and proportional on a 1440px desktop, with no media queries and no layout shift. This tutorial walks through building a complete fluid type scale.
What Clamp() Does
The clamp() function takes three arguments: a minimum, a preferred value, and a maximum. The browser picks the preferred value, but clamps it to never go below the minimum or above the maximum.
For typography, the preferred value is usually a viewport-relative expression like "4vw plus 12px". As the viewport grows, the preferred value grows. The minimum and maximum stop it from going too small or too large.
The Basic Formula
A fluid heading that goes from 24px on mobile to 48px on desktop looks like this:
font-size: clamp(24px, 4vw + 12px, 48px);
On a 320px viewport, 4vw is 12.8px, so 4vw plus 12px is 24.8px. The browser clamps that to the 24px minimum. On a 1200px viewport, 4vw is 48px, so 4vw plus 12px is 60px. The browser clamps that to the 48px maximum. Between 320px and 1200px, the font size scales smoothly.
Picking the Minimum and Maximum Viewport
The formula needs to know the viewport range you are designing for. A common choice is 320px (smallest phone) to 1200px (typical laptop). If your layout breaks below 320px or above 1200px, adjust accordingly.
The slope of the fluid scale is the rate at which the font size grows per pixel of viewport. You calculate it as (maxSize minus minSize) divided by (maxViewport minus minViewport). For a 24px to 48px scale over 320px to 1200px, the slope is 24 divided by 880, which is 0.0273.
Building a Full Type Scale
A type scale is not one font size, it is a set of them (xs, sm, base, lg, xl, 2xl, 3xl, and so on). To build a fluid type scale, you apply the same formula to each step, but scale the minimum and maximum by your chosen ratio.
If your base size goes from 16px to 20px and your ratio is 1.2 (minor third), your scale looks like this:
- xs: clamp(11px, 0.7vw plus 8px, 14px)
- sm: clamp(13px, 0.9vw plus 9px, 17px)
- base: clamp(16px, 1.1vw plus 11px, 20px)
- lg: clamp(19px, 1.3vw plus 13px, 24px)
- xl: clamp(23px, 1.6vw plus 16px, 29px)
- 2xl: clamp(28px, 1.9vw plus 20px, 35px)
Each step uses the same slope (derived from the base step) so the entire scale grows in proportion as the viewport widens.
Generating the CSS
The FontBlend fluid type generator computes all of this for you. You set the base min size, base max size, ratio, and viewport range, and it generates the full CSS block with a custom property per step. You copy the output and paste it into your stylesheet.
The generated CSS uses custom properties so you can reference them throughout your design:
:root {
--font-size-base: clamp(16px, 1.1vw + 11px, 20px);
--font-size-lg: clamp(19px, 1.3vw + 13px, 24px);
}
Then in your components: font-size: var(--font-size-lg).
Line Height and Letter Spacing
Fluid typography is not just about size. Line height should also scale, because larger text needs tighter line height and smaller text needs looser line height. A common pattern is to set line height as a unitless value that you adjust per step: 1.6 for xs, 1.5 for base, 1.3 for lg, 1.1 for 2xl and above.
Letter spacing is the same: tighter for large headings (negative), looser for uppercase labels (positive). The FontBlend type scale tool applies these defaults for you.
Browser Support and Fallbacks
clamp() has been supported in all major browsers since 2020. If you need to support older browsers, provide a fallback before the clamp declaration:
font-size: 18px;
font-size: clamp(16px, 1.1vw + 11px, 20px);
The browser uses the second declaration if it supports clamp(), otherwise it falls back to the first.
The Math Behind the Preferred Value
The preferred value is a straight line: slope times viewport plus an intercept. You already have the slope from the range calculation. The intercept is whatever makes the formula land on the minimum at the minimum viewport.
For the 24px to 48px example over a 320px to 1200px range, the slope is 0.0273 pixels of size per pixel of viewport. At 320px that slope contributes 8.74px, so the intercept must supply the other 15.26px. The real declaration is therefore clamp(24px, 2.73vw + 15.26px, 48px). Check both ends: at 320px the preferred value is 24px, and at 1200px it is 48.02px, a rounding sliver that the maximum clamps away. The two-decimal intercept matters because a one-pixel error at the low end shows up as a visible bump on small phones.
A Worked Scale You Can Copy
Here is a complete two-step scale with a base that slides from 18px to 24px over a 480px to 1440px range, using a 1.2 ratio. The base step has a slope of 6px over 960px, which is 0.00625 pixels per pixel, written as 0.625vw, and an intercept of 15px, so the declaration is clamp(18px, 0.625vw + 15px, 24px). The next step up runs from 21.6px to 28.8px, slope 0.0075, intercept 18px, so it reads clamp(21.6px, 0.75vw + 18px, 28.8px).
Watch what the intercepts do. Each step's intercept equals the minimum size of the step below it plus a little, which is why the steps stay evenly spaced at every viewport instead of drifting apart or colliding as the screen narrows. If you change the range, recompute every step; reusing an intercept from an older range is how scales quietly break on exactly one device size.
Common Mistakes
Forgetting the fallback order. The plain declaration must come before the clamp line, because older browsers ignore the line they cannot parse and keep the one before it.
Using vw without a floor and a cap. A heading set to 4vw alone is about 13px on a 320px phone and over 100px on a 4K monitor. The min and max arguments exist to stop both failures.
Choosing a maximum viewport wider than the layout. If your content column stops growing at 1200px but the formula keeps scaling to 1920px, the heading keeps growing after the page around it froze. Set the max viewport where your layout actually stops, not where the monitor ends.
Making every step fluid. The display steps above the base benefit most. Captions and fine print at the bottom of the scale gain little from a slope and are harder to keep legible while sliding, so a static size there is a reasonable choice.
Questions That Come Up
Does fluid type break the WCAG text resize rule? No, because browser zoom scales the whole page including clamp values. The WCAG 1.4.4 concern is text that resists resizing, and a px-based clamp resizes normally under zoom. Keep a floor on body text and the reflow expectations hold.
Why not stick with media queries? Breakpoints jump between two or three fixed sizes, so somewhere in the range the type is always a compromise. Fluid type trades the jump for a continuous curve. You can still keep breakpoints for layout; fluid type and a grid respond to different things.
How do I know the scale is right? Resize the window slowly and watch two things: the ratio between adjacent steps should stay steady, and no step should visibly pass another. The draggable preview pane in the fluid type generator is built for exactly this check.
Should the values be rem instead of px? clamp works with any length unit, and rem keeps the scale tied to the root font size that some users raise in their browser settings. If the site already sets sizes in rem, write the clamp in rem too; the ratio between steps is what matters, not the unit. Derive the values in px first, then convert the finished scale to rem in one pass, because mixing units inside a scale invites rounding errors at the step boundaries.
What if the scale looks right at both ends but wrong in the middle? The middle is where the intercept and rounding do their work. Recompute the intercept for the step instead of nudging individual values, because hand-tuned steps drift apart the moment the viewport lands between the two sizes you tuned.
Related Tools
The FontBlend fluid type generator builds the full scale and exports the CSS. The type scale tool builds a non-fluid modular scale for comparison. The typography playground lets you test the scale against real layout presets.
Related Tools
More Articles
Type Scale Ratios: Minor Third to Perfect Fourth
A comparison of common type scale ratios (minor third, major third, perfect fourth, golden ratio) with the same body size, side by side.
11 min read
Design Tokens Export: From Brand Kit to Code
A walkthrough of exporting a brand kit (colors, type scale, fonts) as JSON tokens, CSS variables, and Tailwind config, with the FontBlend brand kit tool.
12 min read