A title that reads well on a large screen often shrinks to nothing on mobile, or the other way round, a comfortable mobile title overflows on desktop. The classic fix stacks one Media query per screen tier, to adjust font-size each time. clamp() replaces that pile of rules with a single line that computes a fluid size between two bounds.
min() and max() are the two simpler building blocks clamp() is made from, and each has its own use outside of typography.
Definition
clamp(min, preferred, max) takes three values: a minimum, a preferred value that usually varies with screen size, and a maximum. The browser keeps the preferred value as long as it sits between the two bounds, and switches to the minimum or maximum the moment it goes past them.
h1 {
font-size: clamp(1.75rem, 1.2rem + 2vw, 3rem);
}On a small screen, 1.2rem + 2vw drops below 1.75rem: the minimum applies. On a very large screen, that same expression exceeds 3rem: the maximum takes over. In between, the title grows continuously with the width of the window.
How the browser picks a value
| Situation | Value used |
|---|---|
| Preferred < minimum | The minimum |
| Preferred between the two bounds | The preferred value |
| Preferred > maximum | The maximum |
min() and max(), the simpler building blocks
min() keeps the smallest value in a list, max() the largest. They are often used on their own, without going through clamp(), for simpler cases than a fluid size.
.container {
width: min(
90%,
600px
); /* never wider than 600px, but still fluid below that */
}
.text {
font-size: max(1rem, 3vw); /* never smaller than 1rem, whatever the screen */
}clamp(min, preferred, max) is actually the same as writing max(min, min(preferred, max)): all three functions share the same comparison logic, clamp() being just a shortcut for the most common three-value case.
What fluid typography needs to keep
Using only Viewport units in the preferred part, with no fixed portion at all, ignores the text size setting some users configure in their browser for easier reading. Keeping a rem component in the expression, like 1.2rem + 2vw rather than 4vw alone, lets the size keep reacting to that accessibility setting while staying fluid.
Beyond typography
clamp() is not limited to font-size: a container's width follows exactly the same logic, for instance width: clamp(300px, 50%, 800px);, which stays fluid between two fixed bounds instead of jumping abruptly from one value to another at a precise threshold. The preferred value can itself hold a more complex calculation thanks to calc(), which combines several units in the same expression before clamp() compares it against its two bounds.
Frequently asked questions
clamp() work for a colour or a duration?Not for a colour, which has no natural order to compare. Yes, though, for any comparable numeric quantity such as a duration or an angle, even though usage remains overwhelmingly dominated by lengths and text sizes.
The specification handles that case by prioritising the minimum over the maximum, but the visual result becomes hard to predict without rereading the expression. Good practice is still to guarantee yourself that the minimum never exceeds the maximum.
clamp() fully replace media queries?No, it mostly replaces the media queries that only existed to adjust a size or a spacing value. Media queries stay necessary for structural changes, like switching from a stacked navigation to a horizontal one.