Get affordable and hassle-free WordPress hosting plans with Cloudways — start your free trial today.
The CSS calc() function performs math between values, whether that’s addition (+), subtraction (-), division (/), or multiplication (*), along with any other math function.
.element {
height: calc(100vh - 90px);
}
See our “CSS Calculating Function” Guide for a deeper look at the CSS calc() function.
Syntax
This is the formal syntax:
<calc()> = < <calc-sum> >
<calc-sum> = <calc-product> [ [ '+' | '-' ] <calc-product> ]*
<calc-product> = <calc-value> [ [ '*' | / ] <calc-value> ]*
<calc-value> = <number> | <dimension> | <percentage> |
<calc-keyword> | ( <calc-sum> )
<calc-keyword> = e | pi | infinity | -infinity | NaN
Oomph, that’s a lot. To clarify that, we’ve got a calc() function and it equals the sum of some result (<calc-sum>).
- The calculated sum (
<calc-sum>) is a product (<calc-product>) of adding or subtracting values ([ '+' | '-' ]). - The calculated product (
<calc-product>) is a value (<calc-value>) produced by multiplying or dividing values ([ '*' | / ]) that you supply it. - A calculated value (
<calc-value>) can be any CSS number, dimension or percentage. It could also be some calculated keyword (<calc-keyword>) which you can think of as a math keyword to represent a math concept, such as the value ofe(equalsmc2),pi(equals3.14...),infinity(equals no limit!), or not a number (NaN).
So, basically: Plop some numbers and values in the function, add/subtract/divide/multiple them, and wind up with a result. We’ll break this down even more thoroughly as we go along.
The funkiness in the syntax is trying to convey that it’s possible to nest a calc() function in another calc() function, like this:
calc(10px - calc(5px - 3px)); /* 8px */
We’ll get there in a little bit, but you don’t even have to fully write out calc() when it’s nested:
calc(10px - (5px - 3px)); /* 8px */
A few more examples are right up next.
Arguments
/* Basic Arithmetic */
width: calc(100% - 80px);
margin-top: calc(2em * 4);
/* Mixing Units */
font-size: calc(1rem + 2vw);
padding: calc(10px + 1em);
/* Math Functions */
width: calc(min(50%, 600px) - 2rem);
height: calc(max(30vh, 300px) + 1em);
/* With Custom Properties */
margin-left: calc(var(--gap) * 2);
width: calc(100% - var(--sidebar-width) - var(--gap));
/* All together */
width: calc((100% - 40px) / 2 + min(1rem, 20px));
The calc() function takes a single math expression and returns a property value, which can be any of these:
<length>,<frequency>,<angle>,<time>,<flex>,<resolution>,<percentage>,<number>,<integer>,- and any mixed-type value, like
<length-percentage>.
And, yes. It does support CSS Custom Properties, which means we can create variables and reference them in the function.
:root {
--gap: 2rem;
}
section {
margin-left: calc(var(--gap) * 2); /* 4rem */
}
The order of procedures in calc() is the same as the one you were probably taught in school: first we solve parentheses, then multiplication/division, and last we do sums/rests. These are also calculated from left to right.
If we break down each of the parts of calc(), then we would have…
<calc-sum>: Defines addition and subtraction.<calc-product>: Defines multiplication and division.<calc-value>: It is a single self-contained value you can compute with. It can be:<number>: a plain numeric value, e.g.,12,3.5,0.25.<dimension>: a number with a unit, e.g.,10px,2em,5cm. Think “quantity + unit”.<percentage>: a number followed by%, e.g.,50%,12.5%.<calc-keyword>: special constants (see below).( <calc-sum> ): parentheses to group another expression, e.g.,(2 + 3). Example:20px,50%,pi, or(1 + 2).
<calc-keyword>: These are built-in constants, such as:e→ Euler’s number ≈ 2.71828pi→ π ≈ 3.14159infinity→ positive infinity (a value larger than any finite number)-infinity→ negative infinityNaN→ “Not a Number” (an undefined/invalid numeric result)
Basic usage
The calc() function can be used for dynamic sizing and positioning. Say we have a fixed container, such as a header or sidebar. We can use the calc() function to account for the height of the fixed container and subtract it from the remaining space.
For instance, let’s assume we’re building a hero section for a website, and you want it make it fill the entire viewport height. But maybe there is a <nav> bar component just at the top of the hero, and since it’s not accounted for, it’ll push the hero section down a bit, preventing it from taking up the full viewport height. We can fix this using calc() to subtract the <nav> element’s height from the equation so that things fit exactly where they should.
nav { height: 75px; }
.hero {
/* Full dynamic viewport height minus the nav height */
height: calc(100dvh - 75px);
}
Custom properties with calc()
We can use custom properties inside calc() with no issue, which is especially useful when the calculation depends on a variable that is different for each element.
For example, in the “CSS Animations and Transitions” course on Frontend Masters, David Khourshid uses custom properties and calc() to choreograph different elements in one animation. It starts with the following HTML that includes a five .ball elements inside a parent container:
<div class="container">
<div class="ball" style="--i: 0"></div>
<div class="ball" style="--i: 1"></div>
<div class="ball" style="--i: 2"></div>
<div class="ball" style="--i: 3"></div>
<div class="ball" style="--i: 4"></div>
</div>
The variable given to each .ball element is used to calculate its delay, resulting in a staggered arrangement of balls moving from left to right, one after the other, in a vertical stack.
.ball {
--duration: 1s;
--stagger: 0.5s;
--interval: calc(var(--duration) - var(--stagger));
animation: move-right var(--duration) calc(var(--interval) * var(--i)) both;
}
Themed states with calc()
Many CSS color functions accept a series of numeric values to form a color. For example, the hsl() function takes three arguments: one for the hue, one for the saturation, and one for the lightness. We can create variables for each one of those, like this:
:root {
--H: 140;
--S: 80%;
--L: 45%;
}
button {
background-color: hsl(var(--H) var(--S) var(--L));
}
That’s cool! We can take it a little further and adjust those values on hover with the calc() function:
:root {
--H: 140;
--S: 80%;
--L: 45%;
}
button {
background-color: hsl(var(--H) var(--S) var(--L));
/* 10% lighter on hover */
&:hover {
background-color: hsl(var(--H) var(--S) calc(var(--L) + 10%));
}
}
We can do that for all the button states, actually:
Or let’s say we need to use that button in a different color theme. Maybe instead of green, we need it some shade of blue instead. Once again, calc() can make that adjustment for us by calculating a new hue value for that specific instance without us having to find a specific color value ourselves.
:root {
--H: 140;
--S: 80%;
--L: 45%;
}
/* Default button color: green */
.button {
background-color: hsl(var(--H) var(--S) var(--L));
/* 10% lighter on hover */
&:hover {
background-color: hsl(var(--H) var(--S) calc(var(--L) + 10%));
}
}
.button-blue {
background-color: hsl(calc(var(--H) + 50) var(--S) var(--L));
&:hover {
background-color: hsl(calc(var(--H) + 50) var(--S) calc(var(--L) + 10%));
}
}
calc() caveats
Using the calc() function is straightforward. But there are some caveats:
- The result of a
calc()computation will only work if the property it’s used on accepts the resulting value. If that property doesn’t support that value, then the entire declaration is invalid. For instance,width: calc(100% - 20px);would work, whileborder-width: calc(100% - 20px);would not work, because the former property accepts<length-percentage>values, while the latter accepts only<length>values.
.element {
/* Invalid: border-width does not accept % units */
border-width: calc(100% - 20px);
/* Valid: width accepts % and px units */
width: calc(100% - 20px);
}
- The
calc()function requires computable operands to be valid. In other words, the numbers we’re calculating have to be compatible with one another. For example, we cannot subtract a unit-less number, like20, from a unit such as40pxbecause we can’t sum<number>and<length>together.
.element {
/* Invalid: cannot subtract a <number> (20) from a <length> (40px) */
padding: calc(40px - 20);
/* Valid: subjecting a <length> (20px) from another <length> (40px) */
padding: calc(40px - 20px);
}
- We can’t use intrinsic size values inside
calc(). In other words, we can’t use CSS keywords that represent an element’s natural size, such asautoormax-content. If we need to calculate with keywords, use thecalc-size()function instead.
.element {
/* Invalid: cannot use intrinsic sizing keywords */
padding: calc(max-content - 20px);
/* Valid: calc-size() support intrinsic sizing keywords */
padding: calc-size(max-content - 20px);
}
- The
calc()function rounds the value to the nearest integer, rounding by.5when an<integer>(i.e., unit-less number) is expected. It’s important to note that this only happens when the property expects an<integer>value, such as az-indexvalue.
calc(2 - 1.5); /* equals 1 (rounded up by .5) */
calc(2 - 0.6); /* equals 1 (rounded down by .5) */
- We must add a whitespaces between the values when adding or subtracting. That said, the same is not true when we’re dividing or multiplying.
/* Invalid: No whitespaces when adding */
calc(10px+2px);
/* Valid: Includes whitespaces when adding */
calc(100px + 20px);
/* Valid */
calc(10px/2);
calc(10px / 2);
- The second value must be a unit-less integer when dividing or multiplying. It’s a little confusing to remember that since we have to use the same
<length>when adding or subtracting. But it makes sense in that we can only divide a<length>by another<length>that’s the same unit.
/* Invalid: second value is in pixel units */
calc(100px / 5px);
/* Valid: second value is a unit-less integer */
calc(100px / 5);
calc() vs calc-size()
While the calc() and calc-size() functions appear similar at first glance (similar name and similar function), calc() only works with numeric CSS values (e.g., lengths, percentages, numbers, angles, times, etc.), while calc-size() accepts sizing keywords (e.g., min-content, max-content, auto, etc.)
calc() | calc-size() | |
|---|---|---|
| Purpose | Perform mathematical calculations with CSS units (px, %, em, rem, etc.). | Extend intrinsic size keywords (auto, fit-content, min-content, max-content) with math operations. |
| Allowed Inputs | Numeric values + units (px, %, em, rem, vh, etc.) and CSS variables. | Intrinsic size keyword (basis) + calculation expression (using keyword size to reference the basis). |
| Use Case | width: calc(100% - 30px); ensures element fits inside parent minus fixed padding. | width: calc-size(fit-content, size + 20px); ensures element fits its content plus some extra padding. |
| Browser Support | Supported in all modern browsers (Chrome, Edge, Firefox, Safari, and Opera). | Limited support (as of 2025): Chrome 129+, Edge 129+. Not supported in Firefox or Safari yet. |
| When to Use | Everyday layout math (padding, margins, dynamic widths, responsive alignment). | Special cases where intrinsic sizing + animations are needed (e.g., expandable menus, fluid fit-content with adjustments). |
Browser support
The CSS calc() function has full support in all major browsers.
Specification
The calc() function is defined in the CSS Values and Units Module Level 4 specification, which is currently in Editor’s Draft. That means the information can change between now and when it officially becomes a Candidate Recommendation.
More information
- “CSS Animations and Transitions” by David Khourshid (Membership required)
- “The CSS Calculating Function Guide” by Chris Coyier