Comparison
CSS clamp() vs min() and max()
Three comparison functions, one idea: pick a value and keep it within limits. Here is how they relate and when a single limit is enough.
CSS has three comparison functions: min(), max() and clamp(). They all compare values that can have different units, like a percentage and a rem value, and the browser picks one when it lays out the page. Once you see how they relate, choosing between them is easy.
min(): the smallest value wins
min() takes one or more comma-separated values and returns the smallest:
.content {
width: min(100%, 40rem);
}On a narrow screen 100% is smaller, so the content fills its parent. On a wide screen 40rem is smaller, so the content stops there.
This is the part that trips people up: min() sets a maximum. The result can never be larger than any of its arguments, so each argument is an upper limit.
max(): the largest value wins
max() is the mirror image. It returns the largest of its values, which makes each argument a lower limit:
.section {
padding: max(1rem, 4vw);
}On a phone, 4vw is only a few pixels, so the padding holds at 1rem. From 400px wide, 4vw is larger and the padding grows with the screen, without an upper limit.
clamp(): both limits at once
clamp() takes exactly three values: a minimum, a preferred value and a maximum. It returns the preferred value, as long as it stays between the other two:
h1 {
font-size: clamp(2.25rem, 1.667rem + 2.593vw, 4rem);
}The spec defines it as a combination of the other two functions. These two lines always give the same result:
clamp(MIN, VAL, MAX)
max(MIN, min(VAL, MAX))min(VAL, MAX) caps the preferred value at the maximum, and max(MIN, …) then raises the result to at least the minimum. So clamp() is not a new ability, just a shorter and clearer way to write both limits. The guide explains how to read a full clamp value, and the deep dive shows where the numbers in the middle come from.
When one limit is enough
You do not always need both ends. If a value only has to stop in one direction, a single min() or max() is shorter and says more clearly what you mean.
A readable content width
.article {
width: min(100% - 2rem, 70ch);
margin-inline: auto;
}The article is never wider than 70 characters, which keeps lines readable. On small screens it fills the parent minus 1rem on each side. There is no lower limit, because the parent width already is one.
Padding with a floor
.hero {
padding: max(1rem, 4vw);
}The padding never drops below 1rem, and grows freely on large screens. That is fine if the element also has a maximum width. If it can get very wide, add an upper limit with clamp().
Full-bleed sections
.full-bleed {
padding-inline: max(1rem, (100% - 70rem) / 2);
}The background stretches edge to edge, while the content inside stays centred at up to 70rem wide. The percentage refers to the width of the parent, so when the section is narrower than 72rem, the padding holds at 1rem.
When you need clamp()
Use clamp() when a value should grow with the screen but stop at both ends. That covers almost every fluid font size and most fluid spacing: the text should not get too small on a phone, and not too large on a wide monitor. The clamp() generator calculates the preferred value for you.
When the minimum is larger than the maximum
Because clamp() is max(MIN, min(VAL, MAX)), the minimum is applied last. If the minimum is larger than the maximum, the minimum wins:
/* Always 3rem: the minimum is larger than the maximum */
font-size: clamp(3rem, 2vw, 2rem);The browser does not reject the value or show a warning. The size just never changes. This is easy to cause by accident when the minimum and maximum come from different variables, so it is worth checking if a fluid value refuses to move.
Nesting and calculations
Every argument of min(), max() and clamp() is already a calculation. You can add, subtract, multiply and divide inside it without wrapping it in calc():
/* These are the same */
width: min(100% - 2rem, 70ch);
width: min(calc(100% - 2rem), 70ch);The functions can also be nested inside each other, and inside calc(). Custom properties work too:
:root {
--space: clamp(1rem, 0.625rem + 1.563vw, 2.5rem);
}
.stack > * + * {
margin-top: calc(var(--space) * 2);
}
.sidebar {
width: min(max(16rem, 25%), 24rem);
}The last one is clamp(16rem, 25%, 24rem) written out by hand. When you see a max() inside a min(), or the other way around, rewriting it as clamp() is usually easier to read.
A few rules to keep in mind:
- Put spaces around
+and-.100%-2remis invalid,100% - 2remis not. - The units have to make sense together. You can mix lengths and percentages, but not a length and a plain number.
- Percentages resolve the same way they would without the function. In
widththey refer to the parent’s width, infont-sizeto the parent’s font size.
Browser support
min(), max() and clamp() work in all current versions of Chrome, Edge, Firefox and Safari, and have done so since 2020. Unless you support browsers older than that, you can use them without a fallback. The MDN page on clamp() has the exact version numbers.
Summary
min()returns the smallest value, so it sets an upper limit.max()returns the largest value, so it sets a lower limit.clamp(MIN, VAL, MAX)ismax(MIN, min(VAL, MAX)): both limits in one function.- Use a single min() or max() when only one limit matters.
- If the minimum is larger than the maximum, the minimum wins.
clamp(), min() and max() FAQ
What is the difference between clamp(), min() and max() in CSS?
min() returns the smallest of its values, max() returns the largest, and clamp(MIN, VAL, MAX) keeps a value between a lower and an upper limit. clamp() is shorthand for max(MIN, min(VAL, MAX)), so it is the same as using both at once.
Why does min() set a maximum?
min() picks the smallest value, so the result can never be larger than any of its arguments. width: min(100%, 40rem) is at most 40rem, which makes it an upper limit. In the same way, max() picks the largest value and sets a lower limit.
What happens if the minimum in clamp() is larger than the maximum?
The minimum wins. clamp(MIN, VAL, MAX) resolves as max(MIN, min(VAL, MAX)), so after the maximum is applied, the result is raised to the minimum again. The value is then fixed at the minimum and never changes.
Do I need calc() inside clamp(), min() or max()?
No. Each argument of these functions is already a calculation, so you can write min(100% - 2rem, 70ch) or clamp(1rem, 0.625rem + 1.563vw, 2.5rem) directly. Wrapping the argument in calc() also works, it is just not needed.
Which browsers support clamp(), min() and max()?
All current versions of Chrome, Edge, Firefox and Safari support all three functions. They have been available in every major browser since 2020, so you can use them without a fallback unless you support very old browsers.