calc()
is a CSS function that can be used anywhere a <length>
, <frequency>
, <angle>
, <time>
, <number>
, or <integer>
value is allowed. It lets you perform mathematical expressions with addition (+), subtraction (-), multiplication (*), and division (/), and then use the result of the expression as a value for a CSS property that accepts any of the previously-mentioned values.
calc()
is particularly useful for calculating relative values, such as relative widths and heights.
For example, the following example uses the calc()
function to calculate a value for the width of an element relative to its parent’s width:
.el { width: calc(100% - 50% / 3); }
The following example specifies the left margin of an element to be ‘10%’ of its parent’s width plus an extra ’10px’:
.el { margin-left: calc(10% + 10px); }
Check the Examples section for some practical examples and use cases.
The calc()
expression represents the result of the mathematical calculation it contains, using standard operator precedence rules, meaning that an expression is evaluated from the left to the right. Division or multiplication will be precede additions and expressions inside parentheses will be calculated first.
The following apply to the mathematical expression inside a calc()
function:
-
Whitespace is required on both sides of the + and – operators. (The * and / operators can be used without whitespace around them.) For example,
calc(50% -10px)
is considered invalid, because as far as the user agent is concerned, it is just a percentage value followed by a negative integer, not an expression. -
Components of a
calc()
expression can be literal values,attr()
orcalc()
expressions (you can nestcalc()
functions), or<percentage>
values that resolve to one of the preceding types. -
Certain values cannot be added together. For example,
calc(5px - 5px + 10s)
orcalc(0 * 5px + 10s)
are both invalid due to the attempt to add a length and a time.
Official Syntax
<calc()> = calc( <calc-sum> ) <calc-sum> = <calc-product> [ [ '+' | '-' ] <calc-product> ]* <calc-product> = <calc-value> [ '*' <calc-value> | '/' <number> ]* <calc-value> = <number> | <dimension> | <percentage> | ( <calc-sum> )
Where <dimension> is a <number>
immediately followed by a unit identifier. Dimensions are used in CSS to specify distances (<length>
), durations (<time>
), frequencies (<frequency>
), resolutions (<resolution>
), and other quantities.
Whitespace is required on both sides of the + and – operators. (The * and / operaters can be used without whitespace around them.)
Type Checking Inside a calc()
Expression
A math expression has a resolved type, which is one of <length>
, <frequency>
, <angle>
, <time>
, <number>
, or <integer>
. The resolved type must be valid for where the expression is placed; otherwise, the expression is invalid. For example, the resolved type of an expression that is used as a value for the transition-duration
property must be of data type <time>
, otherwise the value is invalid for that property. The resolved type of the expression is determined by the types of the values it contains.
Examples
Example #1: Positioning Background Images
The following example stacks two centered background images on top of each other, with one offset slightly from the other.
.foo { background: url(top.png), url(bottom.png); background-repeat: no-repeat; background-position: calc(50% + 20px) calc(50% + 20px), 50% 50%; }
This will make sure the images are stacked on top of each other while keeping the first image offsetted by ’20px’ to the right and bottom from the position of the center.
View this demo on the Codrops Playground
calc()
can also be used to position a background image with offsets that are relative to the right and bottom sides, instead of the top and left sides, which are the two sides used for offsetting background positions in CSS.
For example, suppose you want to position an image at the bottom right corner of the element’s background area, but you want it to be 20px above the bottom and 20px to the left of the right edge. Using the background-position
offsets, you can’t specify offsets from the bottom and right. For example, background-position: 20px 20px;
would offset the image by ’20px’ from the left and top edges, thus positioning it at the top left corner. But using calc()
, positioning the image relative to the right and bottom edges is as easy as:
.element { background-position: calc(100% - 20px) calc(100% - 20px); }
The following is the live demo:
View this demo on the Codrops PlaygroundExample #2: Margins Relative to Font Size
In this example, we’re using calc()
to calculate the width of an element relative to its parent’s width, and then subtract the amount of margin we want from that width. The value of the margin is set in em
units, which means that the amount is going to be relative to the element’s font size.
The element is going to have a width that is equal to its parent’s width (100%), and then we’re going to subtract the amount of margin that we want:
.child { width: calc(100% - 2em); /* 1em margin on each side */ }
If the font size changes, the margins will adjust. The element is going to be centered inside its parent using <a href="http://tympanus.net/codrops/css_reference/margin">margin</a>: auto;
. Here is the live demo; the container has a purple background color, and the element itself is centered inside it. You can see the margins on both sides. Try changing the value of the font size to see how the margins change.
Similarly, if you want the width of an element to be the same as its parent without counting its own padding, you can do something like this:
.child { padding: 10px; width: calc(100% - 20px); }
The ’20px’ counts for the padding on the left and right of the element.
However, using calc()
to do this kind of math is probably not going to be needed since the box-sizing
property allows us to avoid these calculations altogether. The above width: calc(100% - 20px)
expression is equivalent to saying:
.el { width: 100%; padding: 10px; box-sizing: padding-box; }
We are able to specify the width and padding of our element without having to worry about calculations. Similarly, you can add borders to an element and account for those borders using calc()
, or avoid that altogether using box-sizing
with a value of border-box
.
.el { padding: 10px; border: 2px solid black; width: calc(100% - 20px - 4px); /* subtract the values of the padding and borders so that the element does not become wider than its parent */ } /* OR */ .el { box-sizing: border-box; /* magical! */ padding: 10px; border: 2px solid black; width: 100%; /* without a fuss */ }
You can read more about the advantages of the box-sizing
property, its use cases, and the meaning of its values in the box-sizing
property entry.
More Examples…
Since calc()
can be used anywhere a length value can be used, the following are all valid use cases:
-
Setting the margins of a paragraph:
p { margin: calc(1rem - 2px) calc(1rem - 1px); }
-
The following will place color-stops on a gradient an equal distance from either end.
.foo { background-image: linear-gradient(to right, silver, white 50px, white calc(100% - 50px), silver); }
-
The following sets the
font-size
so that exactly ’40em’ fits within the viewport, ensuring that roughly the same amount of text always fills the screen no matter the screen size.:root { font-size: calc(100vw / 40); }
If the rest of the design is specified using the
rem
unit, the entire layout will scale to match the viewport width. -
The following sets the
line-height
of an element relative to the viewport height:h1 { font: 3em / calc(100vh - 1em) "Lora", sans-serif; }
-
Combined with the power of a preprocessor,
calc()
can be used to create CSS grid systems. It makes calculating widths, margins, and paddings a lot easier. For example, in a six-column grid system, you may have classes like the following:.col-1-6 { /* 1/6th of the width */ width: 16.66% } .col-5-6 { /* 5/6th of the width */ width: 83.333%; }
The above numbers are very intuitive at first glance, and, looking at the numbers alone, it may not be clear how much each column measures relative to the width of the entire system. Using
calc()
, the above can be replaced with:.col-1-6 { width: calc(100% / 6); } .col-5-6 { width: calc(100% / 6 * 5); }
The above mathematical expressions make understanding the proportions and widths much easier.
You can read more on how you can create a grid system usingcalc()
and Sass in this article, and in this article on SitePoint.
Browser Support
calc() as CSS unit value
Method of allowing calculated values for length units, i.e. `width: calc(100% - 3em)`
W3C Candidate Recommendation
Supported from the following versions:
Desktop
- 26
- 16
- 10
- 15
- 6.1
Mobile / Tablet
- 7.0
- 131
- No
- 131
- 132