CSS calc(), min(), max(), and clamp(): Powerful Math Functions
Why CSS Math Functions?
CSS math functions let you perform calculations directly in your stylesheets. Instead of hardcoding values, you can create dynamic sizes that adapt based on context, viewport, or a combination of units.
The calc() Function
calc() performs basic math operations with CSS values. The power of calc() is that you can mix different units:
/* Subtract a fixed header from viewport height */
.content {
height: calc(100vh - 80px);
}
/* Combine percentages with fixed values */
.sidebar {
width: calc(30% - 2rem);
}
/* Complex calculations */
.grid-item {
width: calc((100% - 3 * 20px) / 4);
}calc() Operations
/* Addition */
width: calc(100% + 2rem);
/* Subtraction */
height: calc(100vh - 60px);
/* Multiplication (one value must be a number) */
padding: calc(1rem * 1.5);
/* Division (divisor must be a number) */
width: calc(100% / 3);Important: The + and - operators must have spaces around them. Multiplication and division do not require spaces but it is good practice.
/* WRONG - will not work */
width: calc(100%-20px);
/* CORRECT */
width: calc(100% - 20px);Practical calc() Examples
/* Full width minus sidebar */
.main-content {
width: calc(100% - 300px);
}
/* Centering with offset */
.tooltip {
left: calc(50% - 100px);
}
/* Responsive with minimum gap */
.card {
width: calc(33.333% - 1rem);
margin: 0.5rem;
}The min() Function
min() returns the smallest value from a list of comma-separated values:
/* Width will be whichever is smaller */
.container {
width: min(1200px, 90%);
}If the viewport is wide, 90% might be 1400px — but min() caps it at 1200px. On a small screen, 90% might be 350px — min() uses that instead.
min() as a Responsive Max-Width
/* These are equivalent */
.container {
width: 90%;
max-width: 1200px;
}
.container {
width: min(1200px, 90%);
}Practical min() Examples
/* Image never exceeds its container or 600px */
img {
width: min(100%, 600px);
}
/* Padding that shrinks on small screens */
.section {
padding: min(4rem, 8vw);
}
/* Font size with an upper limit */
h1 {
font-size: min(5vw, 3rem);
}The max() Function
max() returns the largest value from a list:
/* Width will be whichever is larger */
.sidebar {
width: max(300px, 25%);
}The sidebar will always be at least 300px, but will grow to 25% if the viewport is wide enough.
max() as a Responsive Min-Width
/* These are equivalent */
.sidebar {
width: 25%;
min-width: 300px;
}
.sidebar {
width: max(300px, 25%);
}Practical max() Examples
/* Ensure readable line length */
.article {
font-size: max(16px, 1vw);
}
/* Minimum padding regardless of screen size */
.container {
padding: max(1rem, 3vw);
}The clamp() Function
clamp() takes three values: a minimum, a preferred value, and a maximum. It returns the preferred value, clamped between the minimum and maximum:
/* clamp(minimum, preferred, maximum) */
h1 {
font-size: clamp(1.5rem, 4vw, 3rem);
}- If 4vw is less than 1.5rem → uses 1.5rem (minimum)
- If 4vw is between 1.5rem and 3rem → uses 4vw (preferred)
- If 4vw is greater than 3rem → uses 3rem (maximum)
clamp() is Equivalent to
/* These produce the same result */
font-size: clamp(1.5rem, 4vw, 3rem);
font-size: max(1.5rem, min(4vw, 3rem));Fluid Typography with clamp()
body {
font-size: clamp(1rem, 0.5rem + 1vw, 1.25rem);
}
h1 {
font-size: clamp(2rem, 1rem + 3vw, 4rem);
}
h2 {
font-size: clamp(1.5rem, 0.75rem + 2.5vw, 3rem);
}
h3 {
font-size: clamp(1.25rem, 0.5rem + 2vw, 2rem);
}Fluid Spacing with clamp()
.section {
padding: clamp(2rem, 5vw, 6rem) 0;
}
.container {
padding: 0 clamp(1rem, 3vw, 3rem);
}
.card {
gap: clamp(1rem, 2vw, 2rem);
}Nesting Functions
You can nest these functions inside each other and inside calc():
/* Complex responsive width */
.element {
width: calc(min(90%, 1200px) - 2rem);
}
/* Responsive with minimum and calculation */
.container {
padding: max(1rem, calc(5vw - 1rem));
}Summary
CSS math functions eliminate the need for hardcoded values and media queries in many cases. Use calc() for mixing units and performing calculations, min() for upper-bound constraints, max() for lower-bound constraints, and clamp() for values that should stay within a range. These functions are essential for creating truly fluid, responsive designs.