Published October 14, 2026
Here is the scale I use on most sites now. H1 is clamp(2rem, 1rem + 3vw, 3.5rem). H2 is clamp(1.5rem, 1rem + 2vw, 2.5rem). H3 is clamp(1.25rem, 1rem + 1vw, 1.75rem). Body text sits at clamp(1rem, 0.9rem + 0.5vw, 1.25rem). That is the whole system: four lines, no breakpoints, and headings that stay in proportion from a 320px phone to a wide desktop. If you want the reasoning and the checks behind it, keep reading.
The numbers come from one decision, the ratio. I use 1.25, the major third. Body text at 16px times 1.25 gives 20px for H3. Times 1.25 again gives 25px, which I round to 24px for H2. Times 1.25 again gives 30px, which I push to 32px for H1. Each step up the scale multiplies by the same amount, so the eye reads the hierarchy the same way at every size. Hand-picking each heading size separately is how scales drift: H1 ends up shouting, H3 ends up whispering, and nobody notices until the design is live.
The clamp() values then stretch each step across the viewport range. H1 runs 32px to 56px. H2 runs 24px to 40px. H3 runs 20px to 28px. Body runs 16px to 20px. Notice the gaps. At the small end, H1 sits 8px above H2, H2 sits 4px above H3, H3 sits 4px above body. At the large end, the gaps widen to 16px, 12px, and 8px. The hierarchy gets more room as the screen gets bigger, which is exactly what a large screen can afford. A fixed 8px gap at every size would look cramped on desktop and fine on mobile. The fluid version adjusts itself.
Why the CSS clamp() fluid heading scale holds together
Two details do most of the work. First, the preferred values use different vw slopes: 3vw for H1, 2vw for H2, 1vw for H3, 0.5vw for body. The bigger the heading, the faster it grows. That is what keeps the ratio roughly intact mid-range instead of only at the endpoints. Give every heading the same slope and the small headings catch up to the big ones in the middle of the range, which flattens the hierarchy right where most tablets live.
Second, the min and max are in rem. A reader who bumps their browser font size up expects the whole page to follow, headings included. Pure px mins would ignore that setting. Pure vw preferred values would ignore zoom. The rem plus vw preferred value is the compromise that keeps both working: the vw part scales with the viewport, the rem part scales with the reader.
Before shipping a scale, I run three checks. Check the 320px end: H1 at 32px, H2 at 24px, H3 at 20px, body at 16px. If any two adjacent levels land within 4px of each other, widen the gap. Check a mid viewport, say 768px: H1 lands near 39px, H2 near 31px, H3 near 24px, body near 18px. The order should be obvious without measuring. Check the 1280px end: everything should be at or near its max, and H1 near 56px should not feel like a billboard next to 20px body text. If it does, the max is too high, not the scale. On a dense dashboard I would cap H1 at 48px and leave the rest alone.
One opinion, stated plainly: most sites I see have too many heading levels doing too little work. If your page uses H1 through H4 and the H4 looks like bold body text, you do not have four levels, you have three plus decoration. Cut the level. A scale with three honest steps beats a scale with five mushy ones, and the clamp() values get simpler with it.
Frequently asked questions
What is a good CSS clamp() fluid heading scale for H1 to H3?
A scale built on a 1.25 ratio works well: H1 clamp(2rem, 1rem + 3vw, 3.5rem), H2 clamp(1.5rem, 1rem + 2vw, 2.5rem), H3 clamp(1.25rem, 1rem + 1vw, 1.75rem), with body text at clamp(1rem, 0.9rem + 0.5vw, 1.25rem).
What type scale ratio should headings use?
1.25, the major third, is a safe default for body-driven sites. Larger ratios like 1.333 suit display-heavy pages. Pick one ratio and let every heading derive from it instead of hand-picking each size.
Should clamp() heading sizes use rem or px?
Use rem for the min and max so browser zoom and user font settings still work. The preferred value mixes rem with vw, which keeps the fluid part scaling while the rem part respects the reader.
How do you keep H1 and H2 from colliding on small screens?
Check the scale at 320px. If H1 at its min and H2 at its min are less than 4px apart, widen the gap by raising H1 or lowering H2. The min values carry the hierarchy on phones.
Do fluid headings need media queries at all?
Usually not for size. Keep media queries for layout changes, like stacking a hero or swapping navigation, and let clamp() handle the type sizes across the whole range.
Generate your clamp values.