CSS min(), max(), and clamp(): How to Use Them
Learn when to use CSS min(), max(), and clamp() for responsive layouts and type, with runnable examples, accessibility guidance, and troubleshooting.
min(), max(), and clamp() let you express responsive limits directly in a CSS property value. Use min() to choose the smaller candidate, max() to choose the larger, and clamp() to keep a preferred value between a minimum and maximum.
For example, cap a fluid content width with width: min(90%, 70rem), enforce a floor with font-size: max(1rem, 2vw), or scale a heading within bounds using font-size: clamp(1rem, 2.5vw, 2rem).
1. Choose the function that matches your constraint
| Need | Function | Example | What it guarantees |
|---|---|---|---|
| A ceiling | min() |
width: min(90%, 70rem); |
The result is no larger than the smaller candidate. |
| A floor | max() |
font-size: max(1rem, 2vw); |
The result is at least the larger candidate. |
| A floor, fluid preference, and ceiling | clamp() |
font-size: clamp(1rem, 2.5vw, 2rem); |
The preferred value can grow or shrink, but stays within the bounds. |
These are patterns, not universal design tokens. Pick limits that work for your content, layout, and supported clients.
2. Use min() to set a maximum
min(a, b, ...) evaluates its comma-separated candidates and returns the smallest. This makes it useful when a value should respond to available space but stop growing at a cap.
.page {
width: min(90%, 70rem);
margin-inline: auto;
}
.card {
width: min(100%, 32rem);
}
At narrow widths, 90% or 100% can leave room inside the available containing block. When the percentage would become wider than the fixed length, the fixed length wins. Percentages resolve in the context of the property: for width, that generally means the containing block.
With three candidates, the smallest of all three wins:
.panel {
width: min(92%, 70rem, 1200px);
}
Do not confuse the min() function with the min-width property. The function computes a value inside a declaration; the property sets a separate constraint.
3. Use max() to set a minimum
max(a, b, ...) returns the largest evaluated candidate. It is useful when a responsive value can grow, but must never fall below a floor.
.section {
padding: max(1rem, 4vw);
}
.body-copy {
font-size: max(1rem, 1.2vw);
}
For the padding example, the result is at least 1rem. As the viewport grows, 4vw may become the larger candidate. Check both ends of the range: a viewport-based value can be too small on narrow screens or too large on wide screens if it has no corresponding upper bound.
4. Use clamp() for bounded fluid values
clamp(minimum, preferred, maximum) returns the preferred value while it is between the bounds. Below the minimum it returns the minimum; above the maximum it returns the maximum. The preferred expression can use viewport units, percentages, or another valid expression for the property.
h1 {
font-size: clamp(2rem, 5vw, 4.5rem);
}
main {
padding-inline: clamp(1rem, 5vw, 4rem);
}
In the heading rule, 5vw is the fluid preference. The text stays at least 2rem and at most 4.5rem. The second rule applies the same idea to horizontal padding.
The middle argument is not required to use vw. Use the expression that represents the design rule. For example, a percentage may be appropriate for a property whose value is meant to track its containing block. Mixed units can be compared in suitable CSS math contexts, but not every arbitrary unit combination is valid for every property.
5. Build a responsive page with all three
This complete stylesheet shows a capped content column, bounded spacing, and fluid heading size. Save it as styles.css and attach it to a page with the matching elements.
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
.page {
width: min(92%, 72rem);
margin-inline: auto;
padding-block: clamp(1.5rem, 5vw, 4rem);
}
h1 {
max-width: 18ch;
margin-block: 0 1rem;
font-size: clamp(2rem, 5vw, 4.5rem);
line-height: 1.05;
}
.intro {
max-width: 65ch;
font-size: max(1rem, 1.1vw);
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
gap: clamp(1rem, 2vw, 2rem);
}
.card {
padding: clamp(1rem, 2vw, 1.5rem);
border: 1px solid #d7dce2;
border-radius: 0.75rem;
}
The grid combines CSS Grid’s minmax() with the min() math function. min(100%, 18rem) avoids asking a narrow grid track to be wider than its available space, while auto-fit lays out as many columns as fit.
6. Combine or nest expressions carefully
CSS math functions can be combined with calc() and nested inside one another. Use that flexibility when it makes the design constraint clearer, and keep expressions easy to inspect.
.content {
width: min(calc(100% - 2rem), 72rem);
}
.title {
font-size: clamp(2rem, max(1.5rem, 4vw), 4rem);
}
The first rule reserves a total of 2rem from the available width and caps the result at 72rem. The nested example imposes a floor on the preferred term before clamp() applies its overall bounds. In practice, the simpler clamp(2rem, 4vw, 4rem) may communicate the same intent more clearly, so avoid nesting without a reason.
7. Check readability, zoom, and browser support
For text controlled by clamp(), preserve room for users to enlarge text. MDN advises that the maximum relative length should be at least twice the minimum relative length; for example, avoid a narrow ratio between the minimum and maximum when text resizing matters. This guidance is not proof that a particular design is accessible. Test the actual page at browser zoom and text-resize settings, including narrow viewports and long content.
MDN marks min(), max(), and clamp() as Baseline Widely available and documents support across browsers since July 2020. That status is not a guarantee for every legacy browser or embedded web view. Check the support matrix for your project when older clients matter.
8. Debug common problems
| Symptom | Likely cause | Fix |
|---|---|---|
| The value never changes as expected | The fixed candidate is always smaller in min(), or always larger in max(). |
Evaluate each candidate at the viewport or containing-block sizes you care about; verify the intended candidate can actually win. |
| A percentage produces a surprising result | It resolves against the property’s containing context, which may differ from the viewport. | Inspect the relevant containing block and property rules; use a viewport unit only if viewport sizing is intended. |
| Text gets tiny on mobile or huge on desktop | A fluid term has no effective floor or ceiling, or the chosen bounds are unsuitable. | Use clamp() with content-tested bounds, then check zoom and text enlargement. |
| The browser rejects the declaration | An expression uses incompatible or invalid units for that property, or has malformed function syntax. | Check commas, parentheses, and the property’s accepted value types. Simplify the expression and test each candidate. |
| A nested value is difficult to maintain | The expression has accumulated unnecessary layers. | Reduce it to the shortest expression that states the needed floor, preferred value, and ceiling. |
| An older client ignores the rule | The browser or embedded web view is outside the support target for these functions. | Check the project’s compatibility requirements and provide an appropriate fallback declaration if needed. |
9. Performance and maintenance
These functions calculate a property value from its candidates; they are not a substitute for choosing a sensible layout. Prefer a short expression that communicates the constraint. When a value appears wrong, inspect the computed value and the candidates’ resolved values in browser developer tools at a few viewport widths. Avoid adding breakpoint overrides unless the layout genuinely needs a discrete change rather than a fluid constraint.
For maintainability, centralize repeated bounds as custom properties when they represent shared design tokens:
:root {
--content-max: 72rem;
--space-min: 1rem;
--space-max: 4rem;
}
.page {
width: min(92%, var(--content-max));
padding-block: clamp(var(--space-min), 5vw, var(--space-max));
}
No special service or license is needed to use these CSS functions. The practical cost is the time required to choose and verify bounds across real content, viewport sizes, and text enlargement settings.
10. Frequently asked questions
Can I put more than two values in min() or max()?
Yes. Each function accepts a comma-separated list and chooses the smallest or largest resolved candidate, respectively.
Does clamp() require a viewport unit?
No. Its preferred expression can use any suitable value expression for the property. Viewport units are common, but they are only one option.
Is clamp() a replacement for media queries?
It handles continuous scaling with bounds. Media queries remain useful when the layout needs a discrete change, such as rearranging components at a breakpoint.
Can these functions be used with custom properties?
Yes, when the custom properties resolve to values valid for the property and math expression. The shared-token example above uses this pattern.
Or skip the browser setup
If you are capturing a page to document or inspect the result, ScreenshotNeo can return a screenshot from one GET request. See the API documentation for its options.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots, and 1,000 screenshots each month are free with no card; paid plans start at $5 for 3,000. Learn about ScreenshotNeo, then sign up for 1,000 free screenshots a month with no card.


