How CSS clamp() works (formula and examples)

|
web css responsive

clamp(MIN, PREFERRED, MAX) returns the preferred value, but never less than MIN and never more than MAX. The preferred value is usually a formula involving viewport units (vw), which makes the result scale with the browser window. A single line replaces a stack of media queries:

font-size: clamp(1rem, 0.5rem + 2vw, 2rem);

This font-size is at least 1rem (16px), grows as the viewport widens, and never exceeds 2rem (32px). The middle expression 0.5rem + 2vw is the formula that produces the actual size at any viewport width.

The arguments explained

clamp(MIN, PREFERRED, MAX);
  • MIN: lower bound. Result never falls below this.
  • PREFERRED: target value. Usually combines a fixed value with vw to scale.
  • MAX: upper bound. Result never exceeds this.

The browser evaluates PREFERRED at the current viewport, then clips to [MIN, MAX]. If PREFERRED evaluates to something less than MIN, the result is MIN. If greater than MAX, the result is MAX. Otherwise, the result is PREFERRED.

How the preferred value scales

The viewport unit 1vw equals 1% of the browser’s width. At a 1000px viewport, 1vw = 10px. So 2vw = 20px, 5vw = 50px, etc.

For 0.5rem + 2vw (treating 1rem as 16px):

Viewport 2vw 0.5rem + 2vw Clamped (1-2rem)
320px 6.4px 14.4px 16px (MIN)
480px 9.6px 17.6px 17.6px
768px 15.4px 23.4px 23.4px
1024px 20.5px 28.5px 28.5px
1280px 25.6px 33.6px 32px (MAX)
1920px 38.4px 46.4px 32px (MAX)

Below 320px the size is pinned at the 1rem MIN. Above ~1240px it is pinned at the 2rem MAX. Between those points, the font scales linearly.

Deriving clamp() from two breakpoints

The most useful clamp() pattern: start at size A on viewport W₁, end at size B on viewport W₂. Find the formula that connects them.

The preferred value should be a linear function of viewport width: intercept + slope × vw.

\[\text{slope (per vw)} = \frac{B - A}{W_2 - W_1} \times 100\] \[\text{intercept (px)} = A - \text{slope} \times \frac{W_1}{100}\]

For 16px at 320px scaling to 32px at 1280px:

  • Slope per vw: (32 - 16) / (1280 - 320) × 100 = 16 / 960 × 100 = 1.667
  • Intercept: 16 - 1.667 × 3.2 = 10.67px

Final formula:

font-size: clamp(1rem, 10.67px + 1.67vw, 2rem);

Verify at the endpoints:

  • 320px: 10.67 + (320 × 1.67/100) = 10.67 + 5.34 = 16.01px ✓
  • 1280px: 10.67 + (1280 × 1.67/100) = 10.67 + 21.38 = 32.05px ✓

The CSS clamp calculator generates this directly from your two breakpoint values.

Common clamp() patterns

Fluid heading

h1 {
  font-size: clamp(1.75rem, 1.25rem + 2.5vw, 3rem);
}

Scales h1 from 28px at 480px viewport to 48px at 1280px.

Fluid section padding

section {
  padding-block: clamp(2rem, 4vw, 5rem);
}

Vertical padding grows from 2rem on small screens to 5rem on large.

Fluid container width

.container {
  width: clamp(20rem, 90%, 80rem);
}

Container is at least 320px wide, prefers 90% of parent, but never exceeds 1280px.

Fluid grid gap

.grid {
  gap: clamp(1rem, 2vw, 2rem);
}

Gap scales from 16px to 32px linearly with viewport width.

Fluid ratio with rem fallback for accessibility

font-size: clamp(1rem, 0.5rem + 2vw, 2rem);

This pattern combines a rem-based intercept (which respects user font-size preferences) with a vw-based scaling factor. Pure vw formulas can break user zoom in some browsers; mixing rem with vw avoids the problem.

When NOT to use clamp()

clamp() is built for continuous scaling. It works less well when you need:

  • Different layouts at breakpoints (use media queries for layout structure)
  • Discrete typography steps (use CSS variables and media queries for explicit sizes)
  • Conditional rules (@container queries handle these better)
  • Non-monotonic behavior (clamp can only interpolate linearly between two endpoints)

For typography that should jump in discrete steps rather than scale smoothly, fall back to media queries:

.title { font-size: 1.5rem; }
@media (min-width: 768px) { .title { font-size: 2rem; } }
@media (min-width: 1280px) { .title { font-size: 3rem; } }

Browser support

clamp() is supported in all modern browsers (Chrome 79+, Firefox 75+, Safari 13.1+, Edge 79+). For practical purposes, it has been universally available since 2020.

The related functions min() and max() work the same way:

width: min(100%, 80rem);  /* whichever is smaller */
height: max(50vh, 30rem); /* whichever is larger */

clamp(MIN, P, MAX) is mathematically equivalent to max(MIN, min(MAX, P)).

Quick formula reference

For a target size S at viewport V (both in px):

preferred = (S - intercept) / (V / 100) vw + intercept px

Or use the slope/intercept method shown above for any two breakpoints. The CSS clamp calculator generates the full clamp() function from minimum size, maximum size, minimum viewport, and maximum viewport in one step.