CSS Clamp() Generator

A fluid font size uses clamp(MIN, PREFERRED, MAX), where the preferred value is a straight line between two screen widths: slope = (max size − min size) ÷ (max viewport − min viewport). For 16px at 375px rising to 24px at 1440px, the result is clamp(1rem, 0.8239rem + 0.7512vw, 1.5rem).

Browser default is 16px
clamp(1rem, 0.8239rem + 0.7512vw, 1.5rem)
font-size: clamp(1rem, 0.8239rem + 0.7512vw, 1.5rem);
Font size at this width: 20.8751px

The quick brown fox jumps over the lazy dog.

How the CSS clamp() formula works

Fluid type should hit your minimum size at a small screen width, your maximum at a large one, and change in a straight line in between. To build that line, the generator works out the slope and the y-intercept, then converts them into CSS units:

slope = (maxSize − minSize) ÷ (maxViewport − minViewport)
intercept = minSize − slope × minViewport
preferred = (intercept ÷ root)rem + (slope × 100)vw

The slope is multiplied by 100 because 1vw is 1% of the viewport width. The intercept is divided by the root font size so it can be written in rem. The min and max are also converted to rem: clamp(minSize ÷ root rem, preferred, maxSize ÷ root rem).

Worked example: body text

16px at 375px wide, growing to 24px at 1440px, with a 16px root:

  • slope = (24 − 16) ÷ (1440 − 375) = 8 ÷ 1065 = 0.007512
  • intercept = 16 − 0.007512 × 375 = 13.1831px = 0.8239rem
  • vw part = 0.007512 × 100 = 0.7512vw
  • Result: clamp(1rem, 0.8239rem + 0.7512vw, 1.5rem)

Check it at 800px wide: 13.1831 + 0.007512 × 800 = 19.19px, which sits between 16px and 24px as expected.

Worked example: a large heading

32px at 320px wide, growing to 48px at 1280px: slope = 16 ÷ 960 = 0.016667, intercept = 32 − 0.016667 × 320 = 26.6667px. The result is clamp(2rem, 1.6667rem + 1.6667vw, 3rem). At 1280px, 26.6667 + 0.016667 × 1280 = 48px, right on the maximum.

Accessibility: keep the limits in rem (WCAG 1.4.4)

WCAG 2.2 Success Criterion 1.4.4 Resize Text requires that text can be resized to 200% without losing content or function. Browser zoom and the user's default font size both change the size of a rem, but they don't change the size of a vw in the same way. That has two consequences:

  • Never write fluid type as pure vw. font-size: 2vw barely responds to zoom. Always include a rem part in the preferred value, as this generator does.
  • Keep min and max in rem, not px. A px minimum ignores the user's font size setting. A rem minimum scales with it, so readers who need larger text still get it.

The wider the gap between your min and max, the more of the size comes from vw and the less it responds to zoom. A commonly used rule of thumb is to keep the maximum no more than about 2.5 times the minimum, and the generator flags values beyond that. Test the result by zooming to 200% in your browser.

Common mistakes

  • Mixing up the viewport widths and the sizes. The viewport values are screen widths, not font sizes. Use the width of your smallest and largest design frames.
  • Converting with the wrong root. If your html element is set to 62.5%, enter 10 as the root, or every rem value will be off.
  • Hand-calculating vw from one frame. Dividing a size by one screen width gives a pure vw value with no limits. Use the px to vw converter for one-off values, and clamp() for anything that needs a floor and a ceiling.
  • Making every size fluid. Small UI text usually works better at a fixed rem size. Convert those with the px to rem converter and save clamp() for headings and display text.

Frequently asked questions

What do the three values in clamp() mean?

clamp(MIN, PREFERRED, MAX) uses the preferred value as long as it sits between the minimum and maximum. If the preferred value is smaller than MIN, the browser uses MIN; if it is larger than MAX, it uses MAX.

Why does the preferred value mix rem and vw?

The vw part makes the size grow with the screen, and the rem part sets where that growth starts from. Together they draw a straight line between your minimum and maximum sizes. The rem part also lets the size respond to the user's font size setting.

Is clamp() supported in all browsers?

Yes. clamp() works in all current versions of Chrome, Edge, Firefox and Safari. Only very old browsers such as Internet Explorer lack support, and they would ignore the declaration.

Can I use clamp() for spacing, not just font size?

Yes. clamp() works with any length property, including padding, margin, gap and width. The same maths applies: enter the smallest and largest spacing you want and the screen widths where each should apply.

What happens outside the min and max viewport widths?

The size stops changing. Below the minimum viewport width it stays at the minimum size, and above the maximum viewport width it stays at the maximum size.

Can the font get smaller on larger screens?

Yes. Enter a larger size for the min viewport than for the max viewport. The slope becomes negative and the generator puts the smaller size first in clamp(), since clamp() needs its lower bound before its upper bound.