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.