CSS Reference Function

calc()

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() or calc() expressions (you can nest calc() functions), or <percentage> values that resolve to one of the preceding types.
  • Certain values cannot be added together. For example, calc(5px - 5px + 10s) or calc(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 Playground

Example #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 margin: 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.

View this demo on the Codrops Playground

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 using calc() 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
  • 66
  • No
  • 66
  • 60

* denotes prefix required.

  • Supported:
  • Yes
  • No
  • Partially
  • Polyfill

Stats from caniuse.com

Written by

Last updated June 11, 2020 at 10:22 pm by Mary Lou

Do you have a suggestion, question or want to contribute? Submit an issue.