What is the CSS clamp() function?

clamp() is a CSS function that lets a value grow and shrink with the viewport (or any other “fluid” unit), but with a hard minimum and maximum so things don’t get silly.

Think of it as “fluid, but with guardrails.” You get responsiveness without needing a pile of media queries.

Why clamp() is so useful

  • One line replaces multiple breakpoints. Your design scales smoothly instead of jumping.
  • You set the safe limits. No microscopic text on small screens, no billboard text on large monitors.
  • Works for more than font-size. Spacing, widths, gaps, border-radius, line-height… it’s a Swiss army knife.

The CSS clamp() syntax and the mental model

The syntax is always:

clamp(min, preferred, max)

  • min: the smallest value you will allow
  • preferred: the value you want to use most of the time (often fluid)
  • max: the largest value you will allow

How clamp() picks the final value

  1. CSS computes the preferred value (for example, something using vw).
  2. If it’s smaller than min, you get min.
  3. If it’s bigger than max, you get max.
  4. Otherwise, you get the computed preferred.

Rules of thumb for good clamps

  • Use rem for min and max so your sizing respects user zoom / accessibility settings.
  • Use something fluid in the middle, like vw, often mixed with a small base like rem.
  • Test by resizing your browser window horizontally. That’s the whole show.

Your first fluid font-size

In the playground below, click the snippets and then resize your browser window horizontally. Watch the heading scale smoothly, but never go below the minimum or above the maximum.

 .title { font-size: clamp(2rem, 4vw, 5rem); } 
 .title { font-size: clamp(3rem, 1rem + 3vw, 5rem); } 
 *, ::before, ::after { box-sizing: border-box; } .demo { padding: 24px; font-family: system-ui, Arial, sans-serif; max-width: 900px; margin: 0 auto; } .title { margin: 0 0 12px; line-height: 1.1; } .note { margin: 0; opacity: 0.8; } 
 

I scale smoothly, but I have limits.

Tip: resize your browser window horizontally to see the difference.

What the middle value is doing

4vw means “4% of the viewport width.” As the viewport gets wider, that value increases. As it gets narrower, it decreases.

The third snippet uses 1rem + 3vw. That’s a common pattern: a stable base (rem) plus a fluid portion (vw) so it scales nicely even at medium sizes.

Using clamp() for spacing

Fluid type is great, but fluid spacing is where your layouts start feeling “designed” at every width. Let’s clamp padding and gap.

Fluid padding with clamp()

Resize horizontally: the card padding will grow and shrink, but never get too cramped or too huge.

 .card { padding: clamp(12px, 2vw, 28px); } 
 .card { padding: clamp(1rem, 0.5rem + 2vw, 3.2rem); } 
 *, ::before, ::after { box-sizing: border-box; } .wrap { font-family: system-ui, Arial, sans-serif; padding: 24px; max-width: 900px; margin: 0 auto; } .card { border: 2px solid #111; border-radius: 14px; background: #f6f6f6; } .card h3 { margin: 0 0 8px; font-size: 1.1rem; } .card p { margin: 0; opacity: 0.85; } 
 

Padding that behaves

Resize the browser: comfy on small screens, roomy on wide screens.

Fluid gap with clamp()

This one is perfect for grids and flex layouts. Resize horizontally and watch the spacing between items.

 .grid { gap: 12px; } 
 .grid { gap: clamp(10px, 2.5vw, 26px); } 
 .grid { gap: clamp(1.2rem, 0.25rem + 2vw, 3rem); } 
 *, ::before, ::after { box-sizing: border-box; } .page { font-family: system-ui, Arial, sans-serif; padding: 24px; max-width: 900px; margin: 0 auto; } .grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); } .item { border: 2px solid #111; border-radius: 12px; padding: 14px; background: #fff; text-align: center; } @media (max-width: 700px) { .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } } @media (max-width: 480px) { .grid { grid-template-columns: 1fr; } } 
 
One
Two
Three
Four
Five
Six

Using clamp() for layout sizing

You can clamp widths to prevent “too narrow” cards on small screens and “too wide” lines on large screens.

Clamp a card’s width

Resize horizontally: the card follows the viewport, but stays within a nice range.

 .card { width: clamp(240px, 34vw, 520px); } 
 .card { width: clamp(14rem, 34vw, 32rem); } 
 *, ::before, ::after { box-sizing: border-box; } .stage { font-family: system-ui, Arial, sans-serif; padding: 24px; display: grid; place-items: center; min-height: 260px; } .card { border: 2px solid #111; border-radius: 16px; padding: 18px; background: #f6f6f6; } .card h3 { margin: 0 0 8px; } .card p { margin: 0; opacity: 0.85; } 
 

Clamp my width

I’m responsive, but not chaotic.

Clamp max-width for readable text

Long lines are tiring to read. This is a simple, practical use of clamp(): keep paragraphs readable at every screen size.

 .prose { max-width: 48ch; } 
 .prose { max-width: clamp(40ch, 60ch + 2vw, 78ch); } 
 *, ::before, ::after { box-sizing: border-box; } .page { font-family: system-ui, Arial, sans-serif; padding: 24px; max-width: 1100px; margin: 0 auto; } .prose { border: 2px solid #111; border-radius: 16px; padding: 18px; background: #fff; } .prose p { margin: 0; line-height: 1.55; } 
 

This paragraph demonstrates clamped line length. Resize your browser horizontally. The container grows, but not so much that the text becomes a marathon.

Using clamp() for line-height

For beginner-friendly typography: line-height is often better as a range, not a single number. As text size changes, your ideal line-height often changes too.

Clamped line-height example

Resize horizontally and switch snippets. Notice how the text feels more comfortable across different widths. This one is a bit harder to see, but it's there.

 .text { font-size: clamp(1rem, 0.9rem + 0.8vw, 1.8rem); line-height: clamp(1.25, 1.1 + 0.4vw, 1.55); } 
 *, ::before, ::after { box-sizing: border-box; } .shell { font-family: system-ui, Arial, sans-serif; padding: 24px; max-width: 900px; margin: 0 auto; } .panel { border: 2px solid #111; border-radius: 16px; padding: 18px; background: #f6f6f6; } .text { margin: 0; } 
 

Clamp can help typography scale smoothly. Resize your browser and notice how the spacing between lines stays comfortable instead of feeling too tight or too loose.

Real-world patterns with clamp()

Let’s combine a few clamped values the way you actually would in a component: a heading, padding, and button sizing.

A responsive “hero” block

Resize horizontally and watch how multiple things scale together. This is the “one function, many wins” moment.

 .hero { padding: clamp(16px, 3vw, 48px); }

.hero h2 {
font-size: clamp(1.8rem, 1rem + 2.8vw, 3rem);
}

.hero p {
font-size: clamp(1rem, 1.5rem + 0.6vw, 1.25rem);
}

.hero .cta {
padding: clamp(10px, 0.8rem + 0.8vw, 16px) clamp(14px, 1.2rem + 1.2vw, 22px);
font-size: clamp(1rem, 1rem + 0.3vw, 1.4rem);
}
 *, ::before, ::after { box-sizing: border-box; } .page { font-family: system-ui, Arial, sans-serif; padding: 24px; max-width: 1000px; margin: 0 auto; } .hero { border: 2px solid #111; border-radius: 18px; background: #f6f6f6; } .hero h2 { margin: 0 0 10px; line-height: 1.1; } .hero p { margin: 0 0 16px; opacity: 0.85; max-width: 60ch; } .cta { border: 2px solid #111; border-radius: 999px; background: #fff; cursor: pointer; font-weight: 700; } 
 

Clamp makes “fluid” feel intentional

Multiple values scale together: type, spacing, and buttons. Resize the browser horizontally and watch it adapt smoothly.

Common clamp() mistakes (and how to fix them)

Mistake: min is bigger than max

  • Symptom: the value looks “stuck” or behaves weirdly.
  • Fix: make sure min <= max. Always.

Mistake: the middle value isn’t fluid

  • Symptom: it never changes when resizing the browser.
  • Fix: include a fluid unit like vw in the preferred value (often mixed with rem).

Mistake: using only vw for fonts

font-size: 4vw; is fluid, but it has no safety rails. On very small screens it can get tiny, and on very wide screens it can get huge. Use clamp() to keep it sane.

Mistake: mixing units without thinking

Mixing units is allowed, and often great (like 1rem + 2vw). Just make sure the numbers create a sensible range. If in doubt: open DevTools, inspect the element, and look at the computed value while resizing.

Practical clamp() recipes you’ll actually reuse

These are for demonstration purposes only, in the real world, you would use a fluid typography and fluid spacing generator such as Fluid type scale calculator.

Recipe: fluid headings

  • Small heading: clamp(1.25rem, 1rem + 1vw, 1.75rem)
  • Medium heading: clamp(1.5rem, 1rem + 2vw, 2.5rem)
  • Big hero heading: clamp(1.8rem, 1.1rem + 3.2vw, 3.2rem)

Recipe: fluid section padding

  • Tight to roomy: clamp(16px, 3vw, 48px)
  • With rem: clamp(1rem, 0.5rem + 3vw, 3rem)

Recipe: fluid grid gap

  • clamp(10px, 2.5vw, 26px)
  • clamp(0.75rem, 0.25rem + 2vw, 1.75rem)

A tiny clamp() cheat sheet

  • Best beginner pattern: clamp(min-rem, base-rem + fluid-vw, max-rem)
  • Typography: clamp the font-size first, then consider clamping line-height.
  • Layouts: clamp padding, gap, and max-width for readable text.
  • Debug: inspect computed values while resizing the window horizontally.

Conclusion

clamp() is one of those CSS features that makes you feel like you’ve unlocked a secret level: smooth responsiveness, fewer breakpoints, and values that stay within reasonable bounds.

If you only remember one thing: use rem for your min and max, add a little vw in the middle, and resize your browser to sanity-check the whole range.

Learn even more about CSS Clamp() in the CSS Min() Max() Clamp() Interactive Tutorial.