Clamp & Fluid Typography
The clamp() function enables fluid, responsive values that scale smoothly between a minimum and maximum, eliminating the need for multiple breakpoints.
The Old Way
Section titled “The Old Way”/* Multiple breakpoints for responsive typography */h1 { font-size: 24px;}
@media (min-width: 480px) { h1 { font-size: 28px; }}
@media (min-width: 768px) { h1 { font-size: 36px; }}
@media (min-width: 1024px) { h1 { font-size: 42px; }}
@media (min-width: 1280px) { h1 { font-size: 48px; }}
/* Spacing with breakpoints */.section { padding: 20px;}
@media (min-width: 768px) { .section { padding: 40px; }}
@media (min-width: 1024px) { .section { padding: 60px; }}Problems:
- Many breakpoints to maintain
- Jarring jumps between sizes
- Repetitive code
- Difficult to keep consistent
- Doesn’t scale smoothly
The Modern Way
Section titled “The Modern Way”/* Single line replaces all breakpoints */h1 { font-size: clamp(1.5rem, 4vw + 1rem, 3rem);}
.section { padding: clamp(1.25rem, 5vw, 3.75rem);}Benefits:
- Single declaration, no breakpoints
- Smooth scaling between sizes
- Built-in min and max constraints
- Less code to maintain
- Consistent scaling system
Understanding Clamp
Section titled “Understanding Clamp”/* clamp(minimum, preferred, maximum) */font-size: clamp(16px, 4vw, 32px);
/* - Never smaller than 16px - Scales with 4vw (4% of viewport width) - Never larger than 32px*/The Formula
Section titled “The Formula”/* Preferred value formula: *//* preferred = (vw-unit) + (base-adjustment) */
/* Example calculation for 320px to 1200px viewport: *//* font-size: clamp(1rem, 0.5rem + 2vw, 2rem); */
/* At 320px: 0.5rem + (320 × 0.02) = 0.5rem + 6.4px ≈ 1rem (min applies) *//* At 760px: 0.5rem + (760 × 0.02) = 0.5rem + 15.2px ≈ 1.5rem *//* At 1200px: 0.5rem + (1200 × 0.02) = 0.5rem + 24px ≈ 2rem (max applies) */Comparison Functions
Section titled “Comparison Functions”/* Takes the smallest value */.container { width: min(100%, 1200px); /* Same as: max-width: 1200px; width: 100%; */}
.card { width: min(400px, 100% - 2rem);}/* Takes the largest value */.element { width: max(300px, 50%); /* At least 300px, or 50% if larger */}
.sidebar { width: max(250px, 20vw);}Combining Functions
Section titled “Combining Functions”/* Nested functions */.container { padding: max(1rem, min(3vw, 2rem));}
/* clamp() is shorthand for: *//* max(minimum, min(preferred, maximum)) */Practical Examples
Section titled “Practical Examples”Fluid Typography Scale
Section titled “Fluid Typography Scale”:root { --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem); --text-sm: clamp(0.875rem, 0.8rem + 0.375vw, 1rem); --text-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem); --text-lg: clamp(1.125rem, 1rem + 0.625vw, 1.25rem); --text-xl: clamp(1.25rem, 1rem + 1.25vw, 1.5rem); --text-2xl: clamp(1.5rem, 1rem + 2.5vw, 2rem); --text-3xl: clamp(1.875rem, 1rem + 4.375vw, 3rem); --text-4xl: clamp(2.25rem, 1rem + 6.25vw, 4rem);}
h1 { font-size: var(--text-4xl);}h2 { font-size: var(--text-3xl);}h3 { font-size: var(--text-2xl);}p { font-size: var(--text-base);}Fluid Spacing
Section titled “Fluid Spacing”:root { --space-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem); --space-sm: clamp(0.5rem, 0.4rem + 0.5vw, 0.75rem); --space-md: clamp(1rem, 0.8rem + 1vw, 1.5rem); --space-lg: clamp(1.5rem, 1rem + 2.5vw, 3rem); --space-xl: clamp(2rem, 1rem + 5vw, 5rem);}
.section { padding-block: var(--space-xl); padding-inline: var(--space-md);}
.card { padding: var(--space-md); gap: var(--space-sm);}Fluid Container
Section titled “Fluid Container”.container { width: min(100% - 2rem, 1200px); margin-inline: auto;}
/* With fluid padding */.container { width: 100%; max-width: 1200px; margin-inline: auto; padding-inline: clamp(1rem, 5vw, 3rem);}Fluid Grid Gap
Section titled “Fluid Grid Gap”.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); gap: clamp(1rem, 3vw, 2rem);}Fluid Hero Section
Section titled “Fluid Hero Section”.hero { min-height: clamp(400px, 60vh, 800px); padding: clamp(2rem, 8vw, 6rem);}
.hero-title { font-size: clamp(2rem, 5vw + 1rem, 5rem); line-height: 1.1;}
.hero-subtitle { font-size: clamp(1rem, 2vw + 0.5rem, 1.5rem); max-width: clamp(300px, 60%, 600px);}Responsive Images
Section titled “Responsive Images”.hero-image { width: clamp(200px, 50%, 400px); height: auto;}
.icon { width: clamp(24px, 3vw, 48px); height: clamp(24px, 3vw, 48px);}Line Length (Measure)
Section titled “Line Length (Measure)”.prose { /* Optimal reading line length: 45-75 characters */ max-width: clamp(45ch, 100%, 75ch);}
article p { max-width: 65ch; font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem); line-height: clamp(1.5, 1.4 + 0.5vw, 1.8);}Browser Support
Section titled “Browser Support”Supported in all modern browsers. See caniuse.com/css-math-functions.
Performance Considerations
Section titled “Performance Considerations”- Calculated at layout time, very efficient
- No JavaScript required
- Reduces CSS file size (fewer breakpoints)
- Values are computed once per layout
When to Use
Section titled “When to Use”Use clamp() when:
- Creating fluid typography systems
- Building responsive spacing scales
- Setting flexible widths with constraints
- Eliminating unnecessary media queries
- Building design systems with consistent scaling
Use breakpoints when:
- Layout structure needs to change (not just sizes)
- Specific sizes needed at specific viewports
- Component behavior changes at breakpoints
- Design requires distinct “steps” not smooth scaling