Back to Blog
CSSclampminmaxResponsive

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

Master CSS comparison functions for responsive sizing without media queries.

B
Bootspring Team
Engineering
August 4, 2018
6 min read

CSS comparison functions enable responsive sizing without media queries. Here's how to use them effectively.

min() Function#

1/* min() returns the smallest value */ 2.element { 3 /* Width is smaller of: 50% or 500px */ 4 width: min(50%, 500px); 5} 6 7/* Responsive max-width pattern */ 8.container { 9 /* Never exceeds 1200px */ 10 width: min(100%, 1200px); 11 margin: 0 auto; 12} 13 14/* Multiple values */ 15.box { 16 width: min(50vw, 500px, 100%); 17 /* Returns smallest of all three */ 18} 19 20/* With calculations */ 21.responsive { 22 width: min(100% - 40px, 800px); 23 padding: min(5vw, 40px); 24}

max() Function#

1/* max() returns the largest value */ 2.element { 3 /* At least 200px, or 20% if larger */ 4 width: max(200px, 20%); 5} 6 7/* Minimum size pattern */ 8.sidebar { 9 /* Never smaller than 250px */ 10 width: max(250px, 20vw); 11} 12 13/* Ensure readable text */ 14.text { 15 font-size: max(16px, 1rem); 16 /* Never smaller than 16px */ 17} 18 19/* With calculations */ 20.card { 21 height: max(300px, 50vh - 100px); 22}

clamp() Function#

1/* clamp(minimum, preferred, maximum) */ 2.element { 3 /* Preferred is 5vw, but: 4 - never smaller than 16px 5 - never larger than 24px */ 6 font-size: clamp(16px, 5vw, 24px); 7} 8 9/* Responsive typography */ 10.heading { 11 font-size: clamp(1.5rem, 4vw, 3rem); 12} 13 14.body-text { 15 font-size: clamp(1rem, 2.5vw, 1.25rem); 16} 17 18/* Responsive spacing */ 19.section { 20 padding: clamp(20px, 5vw, 80px); 21 margin-bottom: clamp(2rem, 6vw, 6rem); 22} 23 24/* Responsive widths */ 25.card { 26 width: clamp(280px, 30vw, 400px); 27}

Fluid Typography#

1/* Base fluid typography */ 2:root { 3 --font-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem); 4 --font-sm: clamp(0.875rem, 0.8rem + 0.4vw, 1rem); 5 --font-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem); 6 --font-lg: clamp(1.125rem, 1rem + 0.6vw, 1.25rem); 7 --font-xl: clamp(1.25rem, 1.1rem + 0.8vw, 1.5rem); 8 --font-2xl: clamp(1.5rem, 1.2rem + 1.5vw, 2rem); 9 --font-3xl: clamp(2rem, 1.5rem + 2.5vw, 3rem); 10} 11 12h1 { font-size: var(--font-3xl); } 13h2 { font-size: var(--font-2xl); } 14h3 { font-size: var(--font-xl); } 15p { font-size: var(--font-base); } 16 17/* Alternative calculation for predictable scaling */ 18.fluid-text { 19 /* Scale from 16px at 320px viewport to 24px at 1200px viewport */ 20 font-size: clamp( 21 1rem, 22 0.727rem + 1.136vw, 23 1.5rem 24 ); 25}

Fluid Spacing#

1/* Fluid spacing scale */ 2:root { 3 --space-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem); 4 --space-sm: clamp(0.5rem, 0.4rem + 0.5vw, 1rem); 5 --space-md: clamp(1rem, 0.8rem + 1vw, 2rem); 6 --space-lg: clamp(1.5rem, 1rem + 2.5vw, 4rem); 7 --space-xl: clamp(2rem, 1.5rem + 3vw, 6rem); 8} 9 10.section { 11 padding-block: var(--space-lg); 12} 13 14.card { 15 padding: var(--space-md); 16 margin-bottom: var(--space-sm); 17} 18 19/* Fluid gap */ 20.grid { 21 display: grid; 22 gap: clamp(1rem, 2vw, 2rem); 23}

Container Widths#

1/* Fluid container */ 2.container { 3 width: min(100% - 2rem, 1200px); 4 margin-inline: auto; 5} 6 7/* Multiple breakpoints effect */ 8.container-fluid { 9 width: clamp(300px, 90%, 1400px); 10} 11 12/* Content width */ 13.content { 14 /* Readable line length */ 15 max-width: min(65ch, 100% - 2rem); 16 margin-inline: auto; 17} 18 19/* Sidebar layout */ 20.layout { 21 display: grid; 22 grid-template-columns: 23 max(200px, 20%) 24 minmax(0, 1fr); 25 gap: clamp(1rem, 3vw, 2rem); 26}

Responsive Components#

1/* Card component */ 2.card { 3 width: clamp(280px, 100%, 400px); 4 padding: clamp(1rem, 3vw, 2rem); 5 border-radius: clamp(8px, 1vw, 16px); 6} 7 8.card-title { 9 font-size: clamp(1.25rem, 3vw, 1.75rem); 10 margin-bottom: clamp(0.5rem, 1vw, 1rem); 11} 12 13/* Button sizes */ 14.button { 15 padding: clamp(0.5rem, 1vw, 0.75rem) clamp(1rem, 2vw, 1.5rem); 16 font-size: clamp(0.875rem, 1.5vw, 1rem); 17 border-radius: clamp(4px, 0.5vw, 8px); 18} 19 20/* Modal */ 21.modal { 22 width: min(90vw, 600px); 23 max-height: min(80vh, 800px); 24 padding: clamp(1rem, 4vw, 2rem); 25}

Aspect Ratio with clamp#

1/* Hero section height */ 2.hero { 3 min-height: clamp(400px, 50vh, 800px); 4 padding: clamp(2rem, 5vw, 6rem); 5} 6 7/* Video container */ 8.video-wrapper { 9 width: clamp(300px, 80%, 1000px); 10 aspect-ratio: 16 / 9; 11} 12 13/* Image sizing */ 14.featured-image { 15 width: clamp(200px, 50%, 600px); 16 height: auto; 17}

Combining with calc()#

1/* Subtract fixed space */ 2.element { 3 width: min(calc(100% - 2rem), 800px); 4} 5 6/* Complex calculations */ 7.sidebar { 8 width: clamp( 9 200px, 10 calc(20% + 50px), 11 350px 12 ); 13} 14 15/* Responsive with fixed elements */ 16.main-content { 17 width: min( 18 calc(100% - var(--sidebar-width) - 2rem), 19 1000px 20 ); 21} 22 23/* Fluid scale calculation */ 24.fluid { 25 /* Linear interpolation between viewport sizes */ 26 --fluid-size: calc( 27 16px + (24 - 16) * ((100vw - 320px) / (1200 - 320)) 28 ); 29 font-size: clamp(16px, var(--fluid-size), 24px); 30}

Use Cases#

1/* 1. Responsive font without media queries */ 2body { 3 font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem); 4} 5 6/* 2. Max-width container */ 7.container { 8 width: min(100% - 40px, 1200px); 9 margin: auto; 10} 11 12/* 3. Minimum tap target */ 13.button { 14 min-width: max(44px, 100%); 15 min-height: max(44px, auto); 16} 17 18/* 4. Flexible sidebar */ 19.sidebar { 20 width: clamp(200px, 25%, 300px); 21} 22 23/* 5. Responsive grid columns */ 24.grid { 25 grid-template-columns: repeat( 26 auto-fill, 27 minmax(min(250px, 100%), 1fr) 28 ); 29} 30 31/* 6. Line length control */ 32.prose { 33 max-width: min(70ch, 100%); 34} 35 36/* 7. Padding that scales but has limits */ 37.section { 38 padding: clamp(1rem, 5vw, 4rem); 39}

Browser Support#

1/* Fallback for older browsers */ 2.element { 3 /* Fallback */ 4 font-size: 18px; 5 6 /* Modern browsers */ 7 font-size: clamp(16px, 4vw, 24px); 8} 9 10/* Feature query */ 11@supports (width: clamp(1rem, 2vw, 3rem)) { 12 .container { 13 width: clamp(300px, 90%, 1200px); 14 } 15} 16 17/* PostCSS plugin can generate fallbacks */ 18.element { 19 width: clamp(200px, 50%, 600px); 20 /* Transpiles to min/max combinations for IE */ 21}

Best Practices#

Use clamp() for: ✓ Typography that scales smoothly ✓ Spacing between breakpoints ✓ Component widths ✓ Padding and margins Use min() for: ✓ Maximum widths (container max-width) ✓ "No larger than" constraints ✓ Responsive with ceiling Use max() for: ✓ Minimum widths ✓ "No smaller than" constraints ✓ Ensuring minimum sizes Tips: ✓ Use rem for font sizes ✓ Use viewport units for preferred values ✓ Set reasonable min/max limits ✓ Test at extreme viewport sizes Avoid: ✗ Over-complicating values ✗ Using px for everything ✗ Ignoring accessibility (min font size) ✗ Forgetting fallbacks for older browsers

Conclusion#

CSS comparison functions (min(), max(), clamp()) enable fluid, responsive designs without media queries. Use min() for maximum constraints, max() for minimum constraints, and clamp() for both. They're perfect for fluid typography, spacing, and container widths. Combine with CSS custom properties for maintainable design systems. Always provide fallbacks for older browsers and ensure minimum sizes meet accessibility requirements.

Share this article

Help spread the word about Bootspring