On this page
Fluid Typography with clamp()
Fluid Typography with clamp(): Complete Guide
Focus keyword: fluid typography. Fluid typography means text that grows smoothly with the screen instead of jumping at breakpoints. With clamp() you set a minimum size, a preferred size that scales with the viewport and a maximum size. In this lesson you will learn the formula behind the preferred value, how to keep fluid text accessible when users zoom, how to build a complete fluid type scale with custom properties, how to choose line height and line length, and how to use container units for component-based typography.
Trending keywords covered in this lesson
fluid typography clamp, responsive font size, clamp rem vw formula, fluid type scale, modular scale CSS, Utopia fluid type, WCAG 1.4.4 resize text, browser zoom accessibility, line-height unitless, measure 65ch, fluid spacing, text-wrap balance, cqi container units typography, variable fonts, font-display swap, vw units problem, type scale CSS variables, responsive headings.
1. From Breakpoints to Fluid Type
The old method sets the font size at each breakpoint: 16px, then 18px, then 20px. The text jumps suddenly at each step. Fluid typography calculates the size continuously between a small screen and a large screen, so one line of CSS replaces several media queries and every screen width gets a well-proportioned size.
2. The clamp() Formula
font-size: clamp(min, preferred, max). The preferred value is a line: intercept + slope * 100vw. To move from size minSize at viewport minVw to size maxSize at viewport maxVw (all in pixels):
- slope = (maxSize - minSize) / (maxVw - minVw)
- intercept = minSize - slope * minVw
- preferred =
intercept (in rem) + (slope * 100) vw
Example: 16px at 320px and 20px at 1200px gives slope 0.004545 and intercept 14.55px, so clamp(1rem, 0.909rem + 0.4545vw, 1.25rem). You can use the JavaScript generator in the last example to calculate it for any pair of values.
3. Accessibility: Keep Text Zoomable
WCAG 1.4.4 requires that text can be resized to 200 percent without loss of content. A font size made only of vw units does not react to browser zoom in the expected way, because zoom changes the viewport width in CSS pixels only slightly for the text. Always include a rem part in the preferred value, and use rem for the minimum and maximum. As a rule of thumb, keep the maximum no larger than about 2.5 times the minimum. Test by zooming to 200 percent and by changing the default font size in the browser settings. Also keep html { font-size: 100% } so the user setting is respected, and never set the root size in pixels.
4. A Fluid Type Scale
A type scale is a set of sizes related by a ratio, for example 1.25 (major third). Use a smaller ratio on small screens, such as 1.2, and a larger ratio on big screens, such as 1.25, so headings have more contrast on large displays. Define the steps as custom properties: --step--1 for small print, --step-0 for body text, and --step-1 to --step-5 for headings. Then write h1 { font-size: var(--step-5); }. The scale is easy to change in one place, and all sizes stay in harmony.
5. Line Height
- Use a unitless
line-heightso it scales with each element font size. - Body text: 1.5 to 1.7.
- Large headings need less: 1.05 to 1.25, because big text looks too loose with a large line height.
- Small text such as captions may need a little more, about 1.6.
- WCAG text spacing guidance expects that users can set line height to 1.5 without breaking the layout, so avoid fixed heights on text containers.
6. Line Length (Measure)
A comfortable line has about 45 to 75 characters. Use the ch unit: max-width: 65ch. On mobile the screen width itself limits the line, and on desktop the max-width does. Combine ch with fluid text and the line length stays readable at every size. Remember that ch depends on the font, so test with your real font.
7. Fluid Spacing
Apply the same idea to spacing so text and space stay in proportion: --space-m: clamp(1rem, 0.8rem + 1vw, 2rem). Use it for padding, margin and gap. Build small tokens such as --space-s, --space-m and --space-l, and multiply them for bigger gaps with calc(). Another useful option is the em unit for spacing inside components: padding in em follows the component font size.
8. Container-Based Fluid Type
Viewport units follow the screen, but a card in a narrow sidebar on a big screen needs smaller text. Container query units solve this: set container-type: inline-size on the parent and use font-size: clamp(1.25rem, 6cqi, 2.5rem) on the child. 1cqi is 1 percent of the container inline size. Always keep a rem part or fixed minimum and maximum so the text still respects zoom.
9. Polish the Typography
text-wrap: balancefor headings creates even line lengths.text-wrap: prettyfor paragraphs avoids a lonely last word. Both are progressive enhancements.font-display: swapin@font-faceshows fallback text immediately while the web font loads.- Variable fonts allow a range of weights and widths in one file, for example
font-weight: 100 900, and can change weight smoothly at different sizes. font-size-adjusthelps the fallback font match the x-height of the web font, which reduces layout jump.- Use
overflow-wrap: break-wordfor long words and URLs. - Use
hyphens: autowith alangattribute on narrow columns of justified or long text.
10. Testing Checklist
- Resize from 320px to 1600px and watch the headings and body text.
- Zoom to 200 percent and to 400 percent. Text must grow and nothing may be cut off.
- Change the default font size in the browser settings.
- Check the longest heading and the longest word.
- Check contrast for both small and large text.
11. Common Mistakes
- Using only
vwfor font size, which breaks accessibility. - Writing clamp arguments in the wrong order.
- Making the maximum much more than 2.5 times the minimum.
- Setting
html { font-size: 62.5% }or pixel sizes and hurting user preferences. - Using a fixed line-height in pixels on text that scales.
- Fluid body text that changes too fast, which feels unstable. Headings can change more than body text.
- Forgetting a measure, so lines become too long on large screens.
- Using fluid type inside a narrow container while basing it on the viewport instead of the container.
Key Takeaways
Use clamp() with a rem-based preferred value so text scales smoothly and still zooms, build a type scale with custom properties, use unitless line height, limit line length with ch, make spacing fluid too, consider container units for components, and always test with zoom and larger default font sizes.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Define four custom properties (--step-0, --step-1, --step-2, --step-3) with clamp(). Each preferred value must include a rem part. Use them for the paragraph, h3, h2 and h1. Give headings a unitless line-height below 1.3 and limit the paragraph to 65ch.
Press Run to execute.
Show expected output
Four --step variables using clamp(minrem, rem + vw, maxrem), headings using var(--step-n) with line-height under 1.3, and the paragraph with max-width: 65chThis is a self-check — compare your result with the expected output above.
This heading uses only viewport units, so it is tiny on phones and ignores browser zoom. Replace it with clamp() so it is never smaller than 1.75rem, never larger than 4rem, and includes a rem part in the preferred value. Also add text-wrap: balance.
Press Run to execute.
Show expected output
h1 uses clamp(1.75rem, X rem + Y vw, 4rem) with a rem term in the middle value and text-wrap: balanceThis is a self-check — compare your result with the expected output above.
Was this page helpful?