Skip to content

Why Your calc() Function in CSS Might Be Broken

4 min read

A CSS bug is a nightmare for every developer. Not only is CSS hard to debug, but it can also go wrong in so many ways.

You've fiddled with the calc() function about a dozen times now but no matter what you try, you can't seem to figure out how to make it work.

Only if writing CSS came to you as naturally as writing JavaScript. You would immediately spot the bug and move on to other tasks.

In this article, you'll learn the common mistake developers make when writing mathematical expressions in CSS.

You'll also learn how to debug calc() and see the computed value change in real-time. You'll finally fix the issue and make sure you'll never have to face it again.

Whitespace and mathematical expressions in CSS

There's a subtle, but important, rule in CSS when it comes to writing mathematical expressions:

The + and - operands must be surrounded by whitespace.

This calc() expression won't work:

.main {
  width: calc(10px+100px); /* ❌ no whitespace surrounding `+` */
}

However, adding whitespace around the + operand fixes the issue:

.main {
  width: calc(10px + 100px); /* ✅ `+` surrounded by whitespace */
}

As a backend developer, I really tripped over this one. In Node.js, whitespace around operands is irrelevant.

MDN has to say the following about how the calc() expression is parsed:

calc(50% -8px) will be parsed as a percentage followed by a negative length — an invalid expression — while calc(50% - 8px) is a percentage followed by a subtraction operator and a length. Likewise, calc(8px + -50%) is treated as a length followed by an addition operator and a negative percentage.

Using our example, the expression calc(10px+100px) is parsed as a length (10px) followed by another (positive) length (+100px).

The plus sign (+) is mistaken for a positive integer sign instead of an addition operator which renders the entire expression invalid.

Adding whitespace around the plus sign: calc(10px + 100px), fixes the issue. The plus sign is now correctly parsed as an addition operator.

The / and * operands don't require whitespace, but adding it is recommend for consistency and to avoid confusion.

How to debug calc()?

Debugging calc() is a bit tricky.

With calc(), the computed value can be different depending on which element it is used. While some expressions such as calc(10px + 10px) always evaluate to the same result, other expressions such as calc(10px + 50%) are dynamic and will change depending on context.

The browser evaluates the expression when it's used with an element. In other words, the final value only exists until it's been used within a property.

An, albeit hacky, way to debug calc() is using Developer Tools in your browser. With DevTools open, select the element you want to apply calc() on, and add a CSS property width to it with the calc() expression. If the expression is invalid it will be negated/struck through.

With DevTools open, 1. Select any element and 2. Add a width property with the calc expression you wish to debug. If the value is struck through, it means the expression is invalid
Debugging a calc() expression in Chrome DevTools

If it's valid, you'll see the result calculated as the width property of the element. In Chrome, the value is visible in the "Computed" tab. If the expression depends on the width of the browser, resize the window to see the value change in real-time.

A calc() expression that depends on browser width is recomputed in real-time on window resize

Avoiding the issue in the future

If you're linting CSS, you can use a rule that warns you when an operand isn't surrounded by whitespace. In Stylelint, this rule is named function-calc-no-unspaced-operator. This is an ideal solution in a working environment where you want to formalise the process among your colleagues.

Unfortunately, linting CSS doesn't cover the scenario when you're using calc() in the sizes attribute of the img tag.

My advice is to always surround mathematical operands in CSS with whitespace. If you make this a strict rule for yourself, you won't face this issue again when writing calc() expressions in CSS.

Write clean code. Stay ahead of the curve.

Every other Tuesday, I share tips on how to build robust Node.js applications. Join a community of 1,537 developers committed to advancing their careers and gain the knowledge & skills you need to succeed.

No spam! 🙅🏻‍♀️ Unsubscribe at any time.

You might also like

Getting Started with Eleventy

My notes on the Egghead course "Getting Started with Eleventy" by Khaled Garbaya.
Read article

A Memory Trick To Remember When to Use for...of vs for...in

When should you use for...of vs for...in? This neat memory trick has saved me countless Google searches.
Read article

Understanding "Property of Undefined" TypeError in JavaScript

Demystifying the often-misleading "TypeError: can't access property of undefined" in JavaScript.
Read article