Fluid Typography With CSS clamp(): A Practical Guide
Use CSS clamp() to size text smoothly between readable minimums and maximums, then check that enlarged text remains usable.
clamp() lets a font size respond continuously to viewport width while staying between a minimum and maximum. Write the bounds first and last, and put the viewport-responsive expression in the middle:
h1 {
font-size: clamp(1.8rem, 2.5vw, 2.8rem);
}
The browser uses the middle value while it falls between the bounds; below that range it uses the minimum, and above it the maximum. Choose those limits for the text and layouts you actually support. Then test the finished page with text enlarged to 200% and check for lost content or functionality.
1. How clamp() works
The syntax is clamp(minimum, preferred, maximum). Its result is equivalent to max(minimum, min(preferred, maximum)).
| Argument | Purpose | Example |
|---|---|---|
| Minimum | Stops the computed size from shrinking below a chosen floor. | 1.8rem |
| Preferred | Sets the value to use when it is within the bounds. Viewport units make it responsive. | 2.5vw |
| Maximum | Stops the computed size from growing beyond a chosen ceiling. | 2.8rem |
For clamp(1.8rem, 2.5vw, 2.8rem), the preferred size grows with the viewport until it reaches the upper limit. On narrow viewports, where it would fall below the lower limit, the minimum wins. The bounds are design choices, not universal typography values.
MDN documents clamp() as widely available across browsers since July 2020. Check its current compatibility table if exact browser versions matter for your project: MDN: clamp() CSS function.
2. Build a readable fluid type rule
Start with one element, choose a minimum and maximum that fit your reading contexts, and use a viewport-relative preferred value between them. This standalone HTML file includes the CSS and content needed to try the rule:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fluid type example</title>
<style>
body {
max-width: 68rem;
margin: 0 auto;
padding: 1.5rem;
font-family: system-ui, sans-serif;
line-height: 1.6;
}
h1 {
font-size: clamp(1.8rem, 2.5vw, 2.8rem);
line-height: 1.15;
}
</style>
</head>
<body>
<main>
<h1>A title that scales with the viewport</h1>
<p>This text stays at the chosen minimum and maximum sizes,
with fluid changes between them.</p>
</main>
</body>
</html>
- Set the minimum to the smallest size that remains readable in the narrowest supported layout.
- Set the maximum to a comfortable size for the widest layout. MDN advises a relative maximum at least twice the relative minimum when
clamp()controls text size. - Choose a preferred expression that scales across the viewport range. A simple
vwvalue is easy to understand, but it may reach either bound quickly; inspect the intermediate widths too. - Check the actual font, line height, wrapping, and surrounding layout at narrow, intermediate, and wide viewport sizes.
- Test enlarged text, including the 200% resize requirement described in the accessibility section below.
For a heading, a smaller minimum and a larger maximum may fit the design. Body text may need different bounds. Do not copy the example values without checking how your font and content behave.
3. Choose between clamp(), fixed sizes, and breakpoints
| Approach | How the size changes | Good fit | Check |
|---|---|---|---|
Fixed font-size |
Stays at one declared size across viewport widths. | Text that should remain consistent across layouts. | Make sure it fits at small and large widths. |
| Media queries | Changes in discrete steps at chosen breakpoints. | Layouts that need deliberate size changes at specific widths. | Check widths just above and below each breakpoint. |
clamp() |
Changes smoothly while the preferred value is between its bounds. | A size that should adapt continuously but must stay within limits. | Check minimum, intermediate sizes, maximum, and enlarged text. |
Using clamp() can make a font-size rule fluid without a media query. It does not replace breakpoints when the layout needs discrete changes, such as a different composition or spacing at a particular width.
4. Check text resizing and accessibility
WCAG 2.2 Success Criterion 1.4.4 requires that, with the stated exceptions for captions and images of text, text can be resized without assistive technology to 200% without loss of content or functionality. MDN recommends a relative maximum at least twice the relative minimum for text controlled by clamp(); this is practical guidance, not a substitute for checking the page. See W3C: Understanding Success Criterion 1.4.4.
- At 200% text size or zoom, inspect headings, paragraphs, navigation, forms, and controls.
- Look for clipped or truncated text, overlapping content, obscured controls, and content that disappears.
- Test narrow as well as wide layouts, because enlarged text may change wrapping and increase page height.
- Confirm controls remain usable and content remains available when text grows.
Viewport units can make type respond to the viewport, but they must not prevent users from enlarging text. W3C lists incorrect use of viewport units to resize text as a common failure. Passing the check depends on the finished page, not just the presence of relative bounds.
5. Common problems and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| The text looks nearly constant. | The preferred expression is already below the minimum or above the maximum over most tested widths. | Check at several viewport widths and adjust the preferred expression or bounds to match the intended range. |
| The text becomes too small on a narrow screen. | The minimum is too low for the font, content, or reading context. | Raise the minimum and recheck wrapping and available space. |
| The text grows too large on desktop. | The maximum is too high or the viewport reaches it earlier than intended. | Choose a more suitable maximum and inspect the line length and layout. |
| Text cannot be enlarged enough. | Viewport-based sizing may not scale as expected, or the maximum bound may constrain it. | Use relative bounds, follow MDN’s guidance that the maximum be at least twice the minimum, and verify the page at 200%. Correct any layout restrictions that cause loss of content or functionality. |
| Text overlaps or gets cut off after resizing. | Fixed-height containers, clipping, or dependent layout rules cannot accommodate larger text. | Allow content to reflow and containers to grow; remove clipping where it hides text or controls, then retest. |
| A comma or argument causes an unexpected result. | clamp() expects three comma-separated expressions in minimum, preferred, maximum order. |
Check the syntax and ensure the intended minimum and maximum are in the correct positions. |
6. Performance, reliability, and maintenance
clamp() is a CSS sizing function; this pattern requires no screenshot service or runtime request. Keep the rule easy to maintain by choosing bounds for the component, checking representative viewport widths, and documenting unusual design constraints near the CSS. Recheck when the typeface, content, or layout changes, since those changes can affect wrapping and fit.
Browser availability is broad, but if your support policy includes older or unusual environments, consult MDN’s current compatibility data and evaluate the page in the environments you support. A fluid size rule alone cannot ensure readable line lengths, suitable line height, or a usable enlarged-text layout.
7. Inspect the result in a browser
After applying the rule, inspect the page at the narrowest supported width, a few intermediate widths, and the widest supported width. Resize the browser to see the fluid transition and use the browser’s zoom or text-resizing facilities to check the accessibility requirement. Look at real page content rather than an isolated heading: long words, buttons, navigation, and form labels expose different layout issues.
If you need screenshots to document those viewport checks, ScreenshotNeo is a website screenshot API and MCP server for developers. Its capture options include viewport and device presets, full-page capture, custom CSS and JavaScript, and waits for a selector, delay, or network idle. See ScreenshotNeo and the API documentation.
Or skip the browser setup
Capture a page with one GET request. This runnable cURL example saves a WebP screenshot:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Equivalent Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Equivalent Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Cookie and consent banners are accepted or removed before capture, along with known newsletter popups and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers say which page verdict and billing status applied. An MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. All features are on every plan. See the ScreenshotNeo docs and sign up for 1,000 free screenshots a month, with no card.
Frequently asked questions
Does clamp() need a media query?
No. It can make a size respond continuously without a media query. Use media queries when the design needs a discrete change.
Can I use clamp() for body text as well as headings?
Yes, but choose and verify bounds separately for each text role. The example values are not universal.
Does using rem guarantee WCAG text resizing?
No. Relative units and suitable bounds help, but the page still needs to work when text is enlarged. Check the rendered content and controls against WCAG 2.2 SC 1.4.4.
What if I need exact browser-version support?
Consult the current compatibility table in MDN’s clamp() reference for the browsers and versions relevant to your support policy.


