Back to Blog
CSSFunctionsResponsiveTypography

CSS clamp(), min(), and max() Functions

Master CSS math functions. From responsive typography to fluid spacing to layout constraints.

B
Bootspring Team
Engineering
August 21, 2020
6 min read

CSS math functions enable responsive designs without media queries. Here's how to use them.

Understanding the Functions#

1/* min() - returns the smallest value */ 2.element { 3 width: min(500px, 100%); 4 /* Uses 100% if smaller than 500px, else 500px */ 5} 6 7/* max() - returns the largest value */ 8.element { 9 width: max(300px, 50%); 10 /* Uses 50% if larger than 300px, else 300px */ 11} 12 13/* clamp() - constrains between min and max */ 14.element { 15 width: clamp(200px, 50%, 800px); 16 /* Minimum 200px, preferred 50%, maximum 800px */ 17} 18 19/* clamp(MIN, PREFERRED, MAX) is equivalent to */ 20.element { 21 width: max(200px, min(50%, 800px)); 22}

Responsive Typography#

1/* Fluid font size */ 2h1 { 3 font-size: clamp(1.5rem, 4vw, 3rem); 4 /* Min: 24px, scales with viewport, Max: 48px */ 5} 6 7/* More control with calc */ 8h1 { 9 font-size: clamp(1.5rem, 1rem + 2vw, 3rem); 10} 11 12/* Different scaling rates */ 13body { 14 font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem); 15} 16 17h1 { 18 font-size: clamp(2rem, 1.5rem + 2vw, 4rem); 19} 20 21h2 { 22 font-size: clamp(1.5rem, 1.25rem + 1.5vw, 2.5rem); 23} 24 25h3 { 26 font-size: clamp(1.25rem, 1rem + 1vw, 2rem); 27} 28 29/* Prevent text from getting too small */ 30.small-text { 31 font-size: max(0.875rem, 0.8rem + 0.25vw); 32} 33 34/* Type scale with clamp */ 35:root { 36 --step--2: clamp(0.69rem, 0.66rem + 0.18vw, 0.80rem); 37 --step--1: clamp(0.83rem, 0.78rem + 0.29vw, 1.00rem); 38 --step-0: clamp(1.00rem, 0.91rem + 0.43vw, 1.25rem); 39 --step-1: clamp(1.20rem, 1.07rem + 0.63vw, 1.56rem); 40 --step-2: clamp(1.44rem, 1.26rem + 0.89vw, 1.95rem); 41 --step-3: clamp(1.73rem, 1.48rem + 1.24vw, 2.44rem); 42 --step-4: clamp(2.07rem, 1.73rem + 1.70vw, 3.05rem); 43} 44 45h1 { font-size: var(--step-4); } 46h2 { font-size: var(--step-3); } 47h3 { font-size: var(--step-2); } 48p { font-size: var(--step-0); }

Fluid Spacing#

1/* Fluid padding */ 2.section { 3 padding: clamp(1rem, 5vw, 4rem); 4} 5 6/* Different horizontal/vertical */ 7.container { 8 padding-block: clamp(2rem, 5vh, 6rem); 9 padding-inline: clamp(1rem, 5vw, 4rem); 10} 11 12/* Fluid gap */ 13.grid { 14 display: grid; 15 gap: clamp(1rem, 3vw, 2rem); 16} 17 18/* Fluid margin */ 19.card { 20 margin-bottom: clamp(1.5rem, 4vw, 3rem); 21} 22 23/* Spacing scale */ 24:root { 25 --space-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem); 26 --space-sm: clamp(0.5rem, 0.4rem + 0.5vw, 1rem); 27 --space-md: clamp(1rem, 0.8rem + 1vw, 2rem); 28 --space-lg: clamp(2rem, 1.5rem + 2.5vw, 4rem); 29 --space-xl: clamp(4rem, 3rem + 5vw, 8rem); 30} 31 32.section { 33 padding: var(--space-lg); 34 margin-bottom: var(--space-xl); 35}

Layout Constraints#

1/* Container with max width */ 2.container { 3 width: min(90%, 1200px); 4 margin-inline: auto; 5} 6 7/* Better: responsive container */ 8.container { 9 width: min(100% - 2rem, 1200px); 10 margin-inline: auto; 11} 12 13/* Sidebar minimum width */ 14.sidebar { 15 width: max(200px, 25%); 16} 17 18/* Content area constraints */ 19.content { 20 width: clamp(300px, 70%, 900px); 21} 22 23/* Full-bleed with max */ 24.full-bleed { 25 width: min(100vw, 100%); 26 margin-inline: calc((100% - 100vw) / 2); 27} 28 29/* Card grid */ 30.card-grid { 31 display: grid; 32 grid-template-columns: repeat( 33 auto-fit, 34 minmax(min(100%, 300px), 1fr) 35 ); 36 gap: clamp(1rem, 3vw, 2rem); 37}

Images and Media#

1/* Responsive image with max */ 2img { 3 width: min(100%, 800px); 4 height: auto; 5} 6 7/* Hero image constraints */ 8.hero-image { 9 width: 100%; 10 height: clamp(300px, 50vh, 600px); 11 object-fit: cover; 12} 13 14/* Avatar sizes */ 15.avatar { 16 width: clamp(2rem, 5vw, 4rem); 17 height: clamp(2rem, 5vw, 4rem); 18 border-radius: 50%; 19} 20 21/* Video container */ 22.video-container { 23 width: min(100%, 1200px); 24 aspect-ratio: 16 / 9; 25} 26 27/* Icon sizing */ 28.icon { 29 width: clamp(1rem, 2vw, 1.5rem); 30 height: clamp(1rem, 2vw, 1.5rem); 31}

Combining with calc()#

1/* Complex calculations */ 2.element { 3 width: clamp(200px, calc(50% - 2rem), 600px); 4} 5 6/* Viewport-based with offset */ 7.hero { 8 height: clamp(400px, calc(100vh - 80px), 800px); 9} 10 11/* Percentage-based scaling */ 12.sidebar { 13 width: max(250px, calc(25% + 1rem)); 14} 15 16/* Golden ratio typography */ 17h1 { 18 font-size: clamp( 19 2rem, 20 calc(1rem + 1.618vw), 21 4rem 22 ); 23} 24 25/* Responsive line height */ 26p { 27 line-height: clamp(1.4, calc(1.2 + 0.5vw), 1.8); 28}

Border and Radius#

1/* Responsive border radius */ 2.card { 3 border-radius: clamp(0.5rem, 2vw, 1.5rem); 4} 5 6/* Large radius for mobile, smaller for desktop */ 7.button { 8 border-radius: min(1rem, 2vw); 9} 10 11/* Responsive border width */ 12.bordered { 13 border-width: clamp(1px, 0.2vw, 3px); 14} 15 16/* Box shadow scaling */ 17.elevated { 18 box-shadow: 0 clamp(2px, 0.5vw, 8px) clamp(4px, 1vw, 16px) rgba(0, 0, 0, 0.1); 19}

Form Elements#

1/* Input sizing */ 2input[type="text"], 3input[type="email"] { 4 padding: clamp(0.5rem, 1.5vw, 1rem); 5 font-size: clamp(0.875rem, 1vw, 1.125rem); 6} 7 8/* Button sizing */ 9.button { 10 padding: clamp(0.5rem, 1vw, 1rem) clamp(1rem, 2vw, 2rem); 11 font-size: clamp(0.875rem, 1vw, 1rem); 12} 13 14/* Form max width */ 15form { 16 width: min(100%, 500px); 17} 18 19/* Input with icon */ 20.input-with-icon { 21 padding-left: clamp(2rem, 4vw, 3rem); 22}
1/* Nav link spacing */ 2.nav-link { 3 padding: clamp(0.5rem, 1vw, 1rem) clamp(0.75rem, 1.5vw, 1.5rem); 4} 5 6/* Logo sizing */ 7.logo { 8 height: clamp(2rem, 4vw, 3rem); 9} 10 11/* Mobile menu breakpoint alternative */ 12.nav-links { 13 gap: clamp(0.5rem, 2vw, 2rem); 14} 15 16/* Hide on small screens using max */ 17@media (max-width: 768px) { 18 .nav-desktop { 19 display: none; 20 } 21}

Practical Examples#

1/* Responsive article */ 2article { 3 max-width: min(65ch, 100% - 2rem); 4 margin-inline: auto; 5 padding: clamp(1rem, 5vw, 3rem); 6} 7 8article h1 { 9 font-size: clamp(1.75rem, 4vw, 3rem); 10 margin-bottom: clamp(1rem, 3vw, 2rem); 11} 12 13article p { 14 font-size: clamp(1rem, 1vw, 1.125rem); 15 line-height: 1.7; 16 margin-bottom: clamp(1rem, 2vw, 1.5rem); 17} 18 19/* Responsive card */ 20.card { 21 padding: clamp(1rem, 3vw, 2rem); 22 border-radius: clamp(0.5rem, 1vw, 1rem); 23 gap: clamp(0.5rem, 1.5vw, 1rem); 24} 25 26/* Modal sizing */ 27.modal { 28 width: clamp(300px, 90%, 600px); 29 max-height: min(90vh, 800px); 30 padding: clamp(1rem, 3vw, 2rem); 31}

Browser Support Fallbacks#

1/* Fallback for older browsers */ 2.element { 3 /* Fallback */ 4 width: 50%; 5 max-width: 800px; 6 min-width: 200px; 7 8 /* Modern browsers */ 9 width: clamp(200px, 50%, 800px); 10} 11 12/* Using @supports */ 13@supports not (width: clamp(1rem, 2vw, 3rem)) { 14 .element { 15 width: 50%; 16 min-width: 200px; 17 max-width: 800px; 18 } 19}

Best Practices#

Typography: ✓ Use rem for min/max bounds ✓ Combine vw with rem in preferred ✓ Test at extreme viewport sizes ✓ Ensure minimum readable size Spacing: ✓ Use consistent scaling ratios ✓ Create spacing variables ✓ Test on mobile and desktop ✓ Consider touch targets Layout: ✓ Prefer min() for max-widths ✓ Use clamp() for flexible sizing ✓ Combine with grid/flex ✓ Test edge cases Avoid: ✗ Too many nested functions ✗ Overly complex calculations ✗ Ignoring accessibility ✗ Forgetting fallbacks

Conclusion#

CSS math functions enable truly fluid designs without media queries. Use clamp() for constrained fluid values, min() for responsive maximums, and max() for responsive minimums. Combine with CSS variables for maintainable design systems.

Share this article

Help spread the word about Bootspring