What is clamp() (CSS)?
clamp() (CSS): The CSS clamp() function picks a value between a minimum and a maximum from a preferred value in between, so one expression replaces several media queries.
clamp(min, preferred, max) returns the preferred value, unless it is smaller than the minimum or larger than the maximum, in which case it returns that bound. It is shorthand for max(min, min(preferred, max)). The preferred value is usually something that changes with the viewport or container, such as 5vw or 50%, and the bounds keep it sane. Because it works anywhere a length, number, angle or time is allowed, one line of clamp() can replace a stack of media queries for font sizes, spacing, column widths and more.
Examples
/* A readable column: at least 20rem, ideally 60% of the parent, never more than 70ch */
.prose { width: clamp(20rem, 60%, 70ch); }
/* Section spacing that breathes on wide screens */
.section { padding-block: clamp(2rem, 6vw, 6rem); }
/* A heading that scales with the viewport but keeps zoom working */
h1 { font-size: clamp(2rem, 1.2rem + 2.5vw, 4rem); }
/* A gap that follows the container */
.grid { gap: clamp(0.75rem, 2cqi, 2rem); }
- Units can be mixed and math is allowed inside without
calc():clamp(1rem, 0.5rem + 2vw, 2rem)is valid as written. - If the minimum is larger than the maximum, the minimum wins. That can happen by accident when both come from variables.
- Only one preferred value. For a curve with more than one segment, nest
clamp()insideclamp(), or usemin()andmax()directly. - It works in custom properties, so a
--space-sectiontoken can be fluid and every component that reads it inherits the behavior.
Accessibility
When the preferred value is a pure viewport unit, the result ignores browser zoom, because vw does not change when the user zooms the page. For text that fails WCAG 1.4.4, Resize Text. Always include a rem term in the preferred value for font sizes, and prefer rem-based bounds; fluid typography goes into the arithmetic. Spacing and widths have no such rule, but very large viewport-based padding on small screens still deserves a check at 320px.
In Tailwind CSS v4
Use an arbitrary value where the expression is a one-off, or define a token in @theme when it will be reused:
@theme {
--spacing-section: clamp(3rem, 8vw, 8rem);
--text-display: clamp(2.25rem, 1.5rem + 3vw, 4.5rem);
}
/* <section class="py-section"> and <h1 class="text-display"> */
Arbitrary values cannot contain spaces, so write the expression without them, py-[clamp(2rem,6vw,6rem)], or with underscores where a space is required, which Tailwind converts back: w-[clamp(20rem,_60%,_70ch)]. Container query units inside clamp() tie the value to the component's own width rather than the page.
In MiniDev
Layout primitives such as Container, Stack and Inset take fixed size steps so pages line up with the spacing scale, and clamp() belongs one level up, on section padding and display headings in marketing pages built with Hero and SectionHeader. Keep component internals on the scale and let the page breathe. The layout category lists the primitives.