Dynamic Calculations in CSS Using calc()

Hero image for Dynamic Calculations in CSS Using calc(). Image by Chris Liverani.
Hero image for 'Dynamic Calculations in CSS Using calc().' Image by Chris Liverani.

As a frontend developer, your CSS toolbox isn't complete without a thorough understanding of calc() and how this powerful function allows us (as developers) to perform dynamic calculations to, determine CSS property values, directly within the stylesheet.

Although it has been available and wellsupported for quite some time, calc() remains a genuine gamechanger for creating responsive layouts and finetuning designs across different screen widths. Using it to blend units, perform arithmetic operations, and integrate variables (both CSS variables and the likes of Sass variables) opens up a lot of possibilities that we could only used JavaScript to implement just a few years earlier...


Syntax and Capabilities

Fundamentally, the calc() function can use addition (+), subtraction (), multiplication (*), and division (/) to calculate property values. It's real power comes from the fact that it supports and allows the mixing of different units within the same expression, such as combining percentages with pixels, or using viewport units (e.g., vw and vh) against dynamic units like percentages or fixed units like pixels or ems.

.element {  width: calc(100% - 80px);  height: calc(50vh + 2em);}

In this example, what I'm doing is attempting to demonstrate calc()'s ability to mix units and operations to provide a dynamic width and height based on a combination of the viewport size ad fixed units.

Here, .element would be 80px less than the width of the parent container and 2em taller than 50% of the viewport height.


Responsive Design / Layout Adjustments

As you might appreciate, this ability to combine dynamic and static values means that we developers can create layouts that adjust smoothly across different screen sizes, even with fixeddimension elements, and often without the need for extensive media queries.

As a really basic example, we can use calc() in combination with viewport units and min/max values to create a dynamic element that doesn't break when the screen gets either too small or too big:

.article {  width: calc(50vw - 10rem);  min-width: 30rem;  max-width: 75rem;}

Here, calc() dynamically calculates the width of articles based on the viewport width (50vw), whilst subtracting a fixed margin (10rem), which makes sure that the content doesn't touch the edges of the screen.

The minwidth and maxwidth properties make sure that our article width doesn't become too narrow or too wide, which would help with readability and maintaining design structure across different devices.


Interoperating with Custom Properties

Where calc() becomes even more powerful is when it is used in conjunction with custom properties (either CSS variables or if you're using a CSS processor Sass or Less variables, etc). I've talked about using Sass variables inside calc() before (it's not quite as simple as you might think), so today let's focus on CSS variables instead.

Here's a quick example:

:root {  --header-height: 20rem;}.main-content {  min-height: calc(100vh - var(--header-height));}

In this example, we're setting the custom variable headerheight, and then using calc() to ensure that the main content of the page is always at a minimum the height of the screen (minus the header).

This may not look like much when the two are quite literally sidebyside in the code block above, but if you imagine a much bigger application where different elements need to react to this same dimension, you can hopefully appreciate the power available here. If you combine the variable with JavaScript (i.e., if the header height actually changes based on scroll position, for example), then it's even more powerful still. It also means that should you decide to update your designs and change the height of your header, then it's a single variable change in :root.


Browser Support and Considerations

Whilst it's fair to say that calc() enjoys pretty comprehensive modern browser support without much in the way of nuances or caveats, it is worth still bearing in mind that complex calculations all have to occur at the clientside, at the time the page is painted. Although in most cases the impact is negligible at best, there can be a performance consideration in using calc(). I would say that it would be wise to avoid overly complex expressions, especially in very dynamic, or performancesensitive contexts.


Categories:

  1. CSS
  2. Front‑End Development
  3. Responsive Development