UI Development

Let’s calc()

Introduction

In the earlier versions of CSS(CSS released in 1996 & CSS2 released in 1998), we don’t have any function to do any arithmetic calculations as those versions do not support the mathematical expressions. Due to this, developers have to either hard code the value for a particular CSS property or need to use JS to calculate the value to assign to particular style property. We can call that a very “bad habit” of CSS.

To overcome this drawback, when CSS3 was released in 1999 with so many awesome features that were not there in its previous versions, one of them was the calc() function which resolved the problem that we discussed above of doing mathematical calculations. Below is an example:

.header{
  /* Subtract 30px from 100% */
  height: calc(100% - 30px);
}

The above example means as long as header height is 100%, subtract 30px from it.

Let’s explore more below about the use of this function.

For Values

calc() is mostly used in setting values of different CSS properties. Below is an example:

.element {
  /* Value of property */
  padding:   calc(1em + 5px);
  width:     calc(100% - 25px);
  height:    calc(100vh - 15px);
}

It can be used only as part of a property or as part of a function too that forms part of a property. Below are the examples of each:

.element {
  /* Part of property */
  padding: 20px calc(1em + 5px);
  margin: 30px calc(2em + 10px);
  border-radius: 5px calc(10px / 2) 3px 2px;
}
.element {
  /* Part of function */
  background-image: linear-gradient(
    to right,
    #eeeeee,
    #eeeeee calc(50% - 5px),
    #cccccc calc(50% + 5px),
    #cccccc);
}

Mixing Units

We can mix different units using calc(). Here are a few examples:

/* em units being mixed with pixel units */
margin: calc(1em + 5px);

/* Percentage units being mixed with em units */
width: calc(100% - 1em);

/* vh units being mixed with pixel units */
height: calc(100vh - 10px);

/* Seconds units being mixed with milliseconds units */
animation-delay: calc(2s + 10ms);

calc() can be preprocessed only if the value that needs to be calculated isn’t relative to anything that is determined at runtime. Otherwise, it can’t be preprocessed & the value will be calculated at runtime only. See the below example for both cases.

/* Value preprocessed */
padding: calc(10px + 1em);

/* Value calculated at run time */
width: calc(100% - 1em);

Math Operators in calc()

Addition & Subtraction

Both numbers need to be lengths for addition & subtraction. Below is an example:

.element {
  /* Valid */
  padding: calc(15px + 5px);
  left: calc(15px - 5px);

  /* Invalid */
  margin: calc(5px + 5);
  top: calc(15px - 5);
}

Multiplication 

Multiplication requires one of the numbers to be unitless. Below is an example:

.element {
  /* Valid */
  padding: calc(5px * 2);

  /* Valid */
  padding: calc(2 * 5px);

  /* Invalid */
  padding: calc(5px * 2px);
}

Division

Division requires the second number to be unitless. Below is an example:

.element {
  /* Valid */
  margin: calc(20px / 2);

  /* Invalid */
  margin: calc(10 / 20px);

  /* Invalid */
  margin: calc(20px / 10px);
}

Nesting calc() 

We can do nesting of calc() but it is not necessary. Let’s see the below example:

.element {
  width: calc(calc(100% / 2) - calc(1em * 2);
}

The above can be written without inside calc() also like this:

.element {
  width: calc((100% / 2) - (1rem * 3));
}

Both will calculate the same value with or without nesting calc().

CSS Variables with calc()

We can use calc() with CSS custom properties. Below is an example:

html {
  --gutter-value: 10px;
}

.main-content{
  padding: calc(var(--gutter-value) * 3);
}

Where calc() won’t work

With Media Queries

calc() will not work when used with media queries.

/* Will not work */
@media (min-width: calc(20em + 1px)) {
  /* Wider than 20em */
}

With Strings

calc() will not work with strings or anything like that.

.element::before {
  /* Will not work */
  content: calc("Test " + "calc");
}
.element::after {
  /* Will not work */
  content: calc("calc " / 2);
}

Important Notes

  • Whitespace plays a vital role while writing the calc() function. There should be no space between calc & the opening parentheses.
    .element {
      /* Invalid */
      margin: calc (30px / 3);
    }
  • Whitespace matters in addition & subtraction.
    .element {
      /* Valid */
      margin: calc(2em + 8px);
    
      /* Invalid */
      margin: calc(2em+8px);
    
      /* Valid */
      margin: calc(2em - 8px);
    
      /* Invalid */
      margin: calc(2em-8px);
    }
  • Whitespace is not needed in multiplication & division but it is advisable to keep it for readability.
    .element {
      /* Valid */
      width: calc(100%/2);
    
      /* Valid */
      width: calc(100% / 2);
    
      /* Valid */
      font-size: calc(1em*2);
    
      /* Valid */
      font-size: calc(1em * 2);
    }

Browser Support

calc() is mostly supported on all browsers. Below is the browser support list:

  • Chrome: 19*
  • Firefox: 4*
  • IE: 11
  • Edge: 12
  • Safari: 6*

*  means that version & up. For more details on browser support, please refer the link below:

https://caniuse.com/#feat=calc

For the browsers that don’t support calc(), We can add a property with value before the one that uses the calc() function like below:

.element {
  height: 95%; /* Fallback */
  height: calc(100% - 1em);
}

 

Thanks for reading it all through & hope you have a better understanding of calc() now.

About The Author