Fluid Design with clamp()
The Problem
Traditional responsive design relies on discrete breakpoints: fixed values at specific viewport widths with abrupt jumps between them. This creates jarring transitions and requires multiple media queries to manage. AI agents typically generate rigid breakpoint-based values (e.g., font-size: 1rem on mobile, font-size: 1.5rem on desktop) instead of using fluid scaling, resulting in more code and a less polished experience.
The Solution
The CSS clamp() function defines a value that scales fluidly between a minimum and maximum, based on a preferred value that usually involves viewport units. This eliminates the need for breakpoints for many sizing concerns.
/* clamp(minimum, preferred, maximum) */
font-size: clamp(1rem, 0.5rem + 1.5vw, 2rem);
- Minimum: The smallest the value will ever be.
- Preferred: The fluid middle value, typically using
vwcombined with arembase. - Maximum: The largest the value will ever be.
Code Examples
Fluid Typography
h1 {
font-size: clamp(1.75rem, 1rem + 2.5vw, 3rem);
}
h2 {
font-size: clamp(1.375rem, 0.875rem + 1.5vw, 2.25rem);
}
h3 {
font-size: clamp(1.125rem, 0.75rem + 1vw, 1.75rem);
}
p {
font-size: clamp(1rem, 0.875rem + 0.25vw, 1.125rem);
}
Fluid Spacing
.section {
padding-block: clamp(2rem, 1rem + 3vw, 5rem);
padding-inline: clamp(1rem, 0.5rem + 2vw, 3rem);
}
.stack > * + * {
margin-block-start: clamp(1rem, 0.5rem + 1vw, 2rem);
}
Fluid Layout Dimensions
.container {
max-width: clamp(20rem, 90vw, 75rem);
margin-inline: auto;
}
.sidebar {
width: clamp(15rem, 25vw, 20rem);
}
.gap-fluid {
gap: clamp(0.5rem, 0.25rem + 1vw, 2rem);
}
Fluid Line Height and Letter Spacing
p {
font-size: clamp(1rem, 0.875rem + 0.25vw, 1.125rem);
line-height: clamp(1.5, 1.4 + 0.2vw, 1.8);
letter-spacing: clamp(0px, 0.02em + 0.01vw, 0.04em);
}
Building the Preferred Value
The preferred value formula follows a pattern:
preferred = base-rem-value + viewport-unit-value
To calculate values that scale between two specific viewport widths:
/*
Scale from 1rem at 320px to 2rem at 1200px:
Slope = (max - min) / (max-viewport - min-viewport)
Slope = (2 - 1) / (75 - 20) = 0.01818rem per rem of viewport
In vw: 0.01818 * 100 = 1.818vw
Intercept = min - slope * min-viewport
Intercept = 1 - 0.01818 * 20 = 0.636rem
Result: clamp(1rem, 0.636rem + 1.818vw, 2rem)
*/
.fluid-text {
font-size: clamp(1rem, 0.636rem + 1.818vw, 2rem);
}
Common AI Mistakes
- Using only breakpoints: Generating multiple
@mediaqueries with fixed values instead of a singleclamp()expression. - Using
vwalone withoutrem: Writingfont-size: clamp(1rem, 3vw, 2rem)where the preferred value is purevw. This prevents the value from scaling with user font-size preferences. Always combinevwwith arembase. - Unrealistic min/max bounds: Setting bounds too close together (no visible fluid range) or too far apart (text becomes unreadable at extremes).
- Forgetting accessibility: Fluid typography using
vwunits can interfere with browser zoom. Always test zoom to 200% and ensure text remains readable. - Using
clamp()where a simplemax-widthsuffices: Not every value needs to be fluid. Useclamp()where smooth scaling improves the experience. - Using pixel values for min/max: Pixels do not scale with user font-size settings. Prefer
remfor min and max values.
When to Use
- Typography: Heading and body font sizes that should scale smoothly between mobile and desktop.
- Spacing: Padding, margins, and gaps that should grow proportionally with the viewport.
- Layout widths: Container widths, sidebar widths, and max-widths that need fluid behavior.
- Not for colors or discrete values:
clamp()works with numeric CSS values. It does not apply to properties likedisplay,color, orgrid-template-columnspatterns.