min(), max() & clamp()
The comparison functions — min(), max(), and clamp() — were introduced in CSS in 2020 and immediately became essential for fluid, responsive design. They reduce or eliminate the need for media queries in many common scenarios by expressing sizing as a range rather than a fixed value. Instead of "16px at mobile, 20px at desktop", you write "between 16px and 20px, scaling smoothly with the viewport".
min() — the smaller of two values
min(a, b) evaluates both arguments and uses whichever is smaller. Think of it as a built-in max-width that works in any context:
/* Equivalent patterns */
.old { width: 100%; max-width: 800px; }
.new { width: min(100%, 800px); }
/* min() with multiple arguments */
.container {
padding-inline: min(5%, 48px); /* max 48px, but scales below 960px viewport */
}
/* min() in grid */
.grid {
grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
}
/* Never let an image grow beyond its natural size */
img {
width: min(100%, var(--image-natural-width, 600px));
}
/* On small screens: min(100%, 800px) evaluates to 100%
On large screens: min(100%, 800px) evaluates to 800px */max() — the larger of two values
max(a, b) uses the larger of two values. It's a built-in min-width — it sets a floor:
/* Font size that scales with viewport but has a minimum */
p { font-size: max(1rem, 1.5vw); }
/* At 600px viewport: max(16px, 9px) = 16px — minimum maintained */
/* At 1600px viewport: max(16px, 24px) = 24px — grows beyond rem */
/* Minimum padding */
.section {
padding-block: max(2rem, 4vh);
/* Never less than 2rem regardless of viewport height */
}
/* Minimum touch target — WCAG recommends 44×44px */
.icon-btn {
width: max(44px, 3rem);
height: max(44px, 3rem);
}
/* max() ensures values never go below a threshold */clamp() — the fluid range function
clamp(min, preferred, max) is effectively max(min, min(preferred, max)) — a min and max applied to a preferred value. The preferred value grows freely between the bounds. This is the foundation of modern fluid typography:
/* Fluid typography — grows between 18px and 28px as viewport grows */
p {
font-size: clamp(1.125rem, 0.5rem + 2vw, 1.75rem);
}
/* Fluid headings — a type scale */
h1 { font-size: clamp(2rem, 5vw + 1rem, 4rem); }
h2 { font-size: clamp(1.5rem, 3vw + 1rem, 2.5rem); }
h3 { font-size: clamp(1.25rem, 2vw + 0.5rem, 2rem); }
/* Fluid spacing */
.section {
padding-block: clamp(2rem, 5vw, 6rem);
}
/* Fluid container */
.container {
width: clamp(320px, 90%, 1200px);
margin-inline: auto;
}The fluid type formula
The preferred value in clamp() can use a linear interpolation formula to smoothly scale between a specific minimum font-size at a minimum viewport width and a maximum font-size at a maximum viewport width:
/*
Target: font grows from 18px at 320px viewport to 28px at 1200px viewport
Formula:
preferred = minSize + (maxSize - minSize) * (100vw - minVW) / (maxVW - minVW)
With numbers:
= 18 + (28 - 18) * (100vw - 320px) / (1200px - 320px)
= 18 + 10 * (100vw - 320px) / 880px
Simplified to calc():
= calc(18px + 10 * ((100vw - 320px) / 880))
= calc(1.125rem + (100vw - 20rem) * (10/880))
In practice, use a tool like utopia.fyi or type-scale.com to generate these values:
*/
/* Example output from Utopia for 18px→28px at 320px→1200px: */
p {
font-size: clamp(1.125rem, 0.6563rem + 1.4583vw, 1.75rem);
}Combining all three
/* A complete fluid design system using just these three functions */
:root {
/* Spacing scale — fluid */
--space-xs: clamp(0.25rem, 0.5vw, 0.5rem);
--space-sm: clamp(0.5rem, 1vw, 1rem);
--space-md: clamp(1rem, 2vw, 1.5rem);
--space-lg: clamp(1.5rem, 3vw, 2.5rem);
--space-xl: clamp(2rem, 5vw, 4rem);
/* Type scale — fluid */
--text-sm: clamp(0.875rem, 0.8rem + 0.25vw, 1rem);
--text-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
--text-lg: clamp(1.125rem, 1rem + 0.75vw, 1.5rem);
--text-xl: clamp(1.5rem, 1.2rem + 1.5vw, 2.5rem);
--text-2xl: clamp(2rem, 1.5rem + 2.5vw, 3.5rem);
/* Container */
--container: min(90%, 1200px);
}
.container {
width: var(--container);
margin-inline: auto;
}
body {
font-size: var(--text-base);
padding: var(--space-md);
}Browser support
All three functions — min(), max(), and clamp() — are supported in all modern browsers (Chrome 79+, Firefox 75+, Safari 11.1+). They are safe to use in production without fallbacks for any site targeting modern browsers. If you need IE11 support (rare), provide a fixed px or rem fallback before the clamp() declaration.