Home / Snippets / Typography /
Fluid heading with clamp()
Headings that scale smoothly across all viewport widths using clamp() — no media query breakpoints needed.
Drag the right edge to resize and watch the headings scale
h1 · clamp(1.75rem, 5vw, 3.5rem)
The quick brown fox
h2 · clamp(1.375rem, 3.5vw, 2.5rem)
Jumps over the lazy dog
h3 · clamp(1.125rem, 2.5vw, 1.875rem)
Pack my box with five dozen
h4 · clamp(1rem, 1.75vw, 1.375rem)
Liquor jugs, quickly now
Quick implementation
h1 {
font-size: clamp(1.75rem, 5vw, 3.5rem);
line-height: 1.1;
letter-spacing: -0.02em;
}
h2 {
font-size: clamp(1.375rem, 3.5vw, 2.5rem);
line-height: 1.15;
letter-spacing: -0.015em;
}
h3 {
font-size: clamp(1.125rem, 2.5vw, 1.875rem);
line-height: 1.2;
}
h4 {
font-size: clamp(1rem, 1.75vw, 1.375rem);
line-height: 1.25;
}
Prompt this to your LLM
Includes role, goal, constraints, two variants, and edge cases to handle.
You are a senior frontend engineer building a fluid type scale
for a design system.
Goal: A heading scale (h1–h4) where every size transitions
smoothly between a defined minimum and maximum as the viewport
width changes — no JavaScript, no media query breakpoints.
Technical constraints:
- Use font-size: clamp(min, preferred, max) on each heading level.
- The preferred value must use viewport units (vw) so the size
scales continuously with the viewport width.
- Use rem for min and max values (base 16px assumed).
- Keep line-height tight for display headings: 1.1 for h1, up
to 1.3 for smaller headings.
- Add letter-spacing: -0.02em on h1, decreasing toward h4.
- Use oklch() for any color values — no hex or rgba.
- Use CSS custom properties (var(--font-display), etc.) for
font-family references where applicable.
Variant A — CSS-only heading scale:
Provide a ready-to-paste CSS block for h1, h2, h3, and h4.
Variant B — CSS custom properties fluid scale:
Define --fluid-h1 through --fluid-h4 as custom properties
using clamp(), then apply them with font-size: var(--fluid-h1)
etc. This makes it easy to reuse the same scale on non-heading
elements (hero text, card titles, pull quotes).
Edge cases to handle:
- Very wide viewports: ensure the max clamp value caps growth
so headings don't become illegible at 4K resolutions.
- Very narrow containers: the min value should remain readable
at 320px (the minimum recommended viewport width).
- Nested or constrained containers (sidebars, cards): because
vw is relative to the viewport, not the container, headings
inside narrow columns can appear too small. Consider using
container queries (cqi units) as an alternative preferred
value if container query support is acceptable.
Return only the CSS (or custom property block for Variant B).
Why clamp() replaces media query breakpoints for typography
Before clamp(), fluid typography required a chain of media queries — one for mobile, one for tablet, one for desktop — with hard steps between them. Every breakpoint was a compromise: the heading was either too large on a narrow screen or too small on a wide one, with an abrupt jump in between. clamp(min, preferred, max) eliminates those jumps entirely. The size transitions smoothly across the entire range; there is no point where the user sees a sudden size change.
The three arguments map directly to three design decisions: the minimum is the smallest readable size at narrow viewports (around 320px), the maximum is the ideal large-screen size, and the preferred value is the fluid engine that drives scaling between them.
How the preferred value creates the fluid range
The preferred value uses viewport units (vw), which makes the font size proportional to the viewport width at all times. For example, 5vw means 5% of the viewport width. At 700px wide that is 35px; at 1400px it is 70px. The clamp() function then constrains that output: if the calculated vw value falls below the minimum, the minimum is used; if it exceeds the maximum, the maximum is used. The heading only scales freely within the range defined by the outer two arguments.
Choosing the right vw coefficient controls how steep the scaling curve is. A large coefficient (like 6vw) means the heading grows faster and hits the maximum earlier. A small coefficient (like 2vw) means slow, subtle growth. You can think of the preferred value as the slope of the type scale.
Calculating min and max from design specs
Start with your design system's type scale for mobile and desktop. If the design specifies an h1 of 28px on mobile and 56px on desktop, convert those to rem (divide by 16): 1.75rem and 3.5rem. Those become your min and max. Then choose a vw value that keeps the preferred value within that range across typical viewport widths.
A useful mental model: at the viewport width where you want the heading to be exactly at its maximum, the vw value should equal the max rem value. For a 3.5rem max heading to hit its peak at 1120px (70rem), you need 3.5rem / 70rem = 5vw. This gives you a mathematically precise preferred value tied to your layout's ideal reading width. Adjust from there based on how fast you want the scale to grow.
A complementary approach is to use a tool like Utopia to generate the full fluid type scale automatically from your min/max viewport widths and font size pairs, then inspect the generated clamp() values to understand the math behind them.