Live Curve Visualization
See the actual flat-ramp-flat shape of your clamp(), with a marker showing exactly where your simulated viewport lands.
Build fluid clamp() values for typography and spacing — with a live curve you can actually see, a full type-scale generator, and CSS, SCSS, or Tailwind output. No media queries, no guesswork.
| Level | Min | Max | clamp() |
|---|
Common elements at a 320px → 1440px viewport range, 16px root. Copy one directly — no configuration needed.
| Element | Min → Max | clamp() |
|---|
| Name | Width | Typical Device |
|---|---|---|
| XS | 320px | Smallest phones (iPhone SE) |
| Mobile | 375–390px | Most modern phones |
| Large Mobile | 430px | Phone max, Plus/Pro Max sizes |
| Tablet | 768px | iPad portrait |
| Desktop | 1280–1440px | Common laptop viewport |
| Wide | 1920px | Full HD desktop monitor |
Every generator can compute a clamp(). Not every one shows you the curve.
See the actual flat-ramp-flat shape of your clamp(), with a marker showing exactly where your simulated viewport lands.
Generate an entire xs–4xl heading scale from one modular ratio, previewed live and stacked, not just a single value.
Scale against the full viewport or a component's own container — pick whichever actually matches how the element is used.
Plain CSS, a CSS custom property, an SCSS variable, or a Tailwind config snippet — whichever your codebase already uses.
Need a fast answer, not a configurator? Grab a ready-made clamp() for H1, body text, or section padding straight away.
Every calculation runs in your browser. Nothing you configure is ever sent anywhere.
Enter your smallest and largest viewport widths, and the size you want at each end.
Drag the simulate-viewport slider and watch the preview text — and the curve marker — respond live.
Grab it as plain CSS, a variable, SCSS, or a Tailwind snippet, and paste it straight into your project.
clamp(MIN, PREFERRED, MAX) picks one of three values based on the current viewport: it uses PREFERRED as long as that stays between MIN and MAX, but locks to MIN below that range and MAX above it. In practice that means a font-size or spacing value that grows smoothly with the screen, then stops growing (or shrinking) once it hits the limits you set — no breakpoints required.clamp() declaration replaces a whole stack of media-query overrides for a single property. You'll still want media queries for layout changes that aren't about size (switching from a 3-column grid to 1 column, hiding a sidebar, reordering flex items) — clamp() only interpolates a number, it can't restructure your markup.container-type: inline-size set on it, so the same component scales correctly no matter how narrow or wide the column it's dropped into. Use cqw for components reused inside sidebars, cards, or modals at different widths; use vw for page-level elements like a hero heading.(maxSize − minSize) ÷ (maxViewport − minViewport) — how fast the value grows per pixel of viewport. Intercept (the y-axis intersection) is minSize − slope × minViewport — the value the line would hit at a viewport width of 0. Multiply the slope by 100 and that's the vw coefficient that goes in the middle of the clamp().clamp() is a CSS function that takes three values — a minimum, a preferred value, and a maximum — and returns whichever one applies at the current viewport width. Before it existed, "responsive font size" meant writing a base size and then overriding it at three or four media-query breakpoints, which produces a value that visibly jumps at each breakpoint instead of scaling smoothly. clamp() collapses all of that into a single declaration that interpolates continuously between two endpoints, then holds steady outside of them.
They're not really competing tools — they solve different problems. clamp() is for a value that should change continuously with viewport width: font-size, padding, a max-width. Media queries are for structural changes that a single interpolated number can't express: switching a grid from 3 columns to 1, hiding a sidebar, changing flex-direction. Most real layouts use both — clamp() for the sizes, media queries for the structure around them.
| clamp() | Media Queries | |
|---|---|---|
| Best for | Continuous scaling of a single value | Structural/layout changes |
| Result | Smooth interpolation, no visible jump | Discrete steps at each breakpoint |
| Lines of CSS | One declaration | One block per breakpoint |
| Can restructure markup? | No — numbers only | Yes |
Every clamp() this tool produces follows the same two-step calculation, sometimes called linear interpolation:
slope = (maxSize − minSize) ÷ (maxViewport − minViewport)
intercept = minSize − (slope × minViewport)
The middle "preferred" value is then written as intercept + (slope × 100)vw — multiplying the slope by 100 converts it from "per pixel" into "per vw unit," since 1vw is defined as 1% of the viewport width. Plug both endpoints back in and you'll get exactly minSize at minViewport and exactly maxSize at maxViewport, with a straight line between them.
A page that jumps from 16px to 20px body text at a single 768px breakpoint has one moment where every line of text on the page reflows at once — that's a real, visible layout shift, and enough of them can hurt your Cumulative Layout Shift score. A clamp()-based size changes by a fraction of a pixel per pixel of viewport width, so there's no single frame where the layout visibly jolts. It's not that clamp() eliminates reflow entirely — it's that it spreads the same total change across the whole scroll of viewport widths instead of dumping it all at one breakpoint.
Rem values are relative to the user's browser base font size — 16px by default, but a real number some visitors change. A font-size written in rem still respects that setting; one written in raw px does not, which is why most style guides and WCAG-adjacent checklists lean on rem for anything text-related. This generator defaults to rem for exactly that reason, though it'll happily output px if that's genuinely what your project needs — we cover the tradeoffs in more depth in our px vs. rem vs. em guide, and you can convert any value between the two with our Pixel to REM Converter.
vw is always relative to the browser's viewport — the entire visible window, full stop. cqw is relative to the nearest ancestor that has container-type: inline-size declared on it, which means the same component can scale differently depending on where it's dropped — full width in a hero section, narrower inside a sidebar card — without you writing separate rules for each context. cqw needs a modern browser (Chrome 105+, Safari 16+, Firefox 110+) and an actual container declared upstream; if neither of those is true yet in your project, stick with vw.