DEV Community

Cover image for Complete Guide to Building Responsive UI with CSS calc
Anton Martyniuk
Anton Martyniuk

Posted on • Originally published at antondevtips.com on

Complete Guide to Building Responsive UI with CSS calc

Introduction

Responsive design ensures that web content looks good and functions well, no matter the screen size. Such design is a must-have in modern web applications.

In today’s post we will learn how to dynamically calculate values for various CSS properties, enhancing the responsiveness and flexibility of your web designs.

What is the calc() CSS Function

The calc() function in CSS allows developers to perform calculations to determine CSS property values. It can perform basic mathematical operations: addition (+), subtraction (-), multiplication (*), and division (/).

Its syntax is straightforward:

element {
    property: calc(expression);
}
Enter fullscreen mode Exit fullscreen mode

Here, expression parameter represents a calculation and its result is used for a CSS property value. Expression can be used with number, integer, percentage, length, frequency, angle, or time values.

In most cases unit like pixels (px), percentages (%), viewport units (vw, vh), em, rem are used in expressions. Expression inside calc() function can use a mix of any of these units, for example:

.content {
    width: calc(100% - 100px);
    height: calc(100vh - 100px);
    font-size: calc(2vw + 5px);
    margin: calc(2rem + 10px);
}
Enter fullscreen mode Exit fullscreen mode

Let’s explore a realistic use case where we create a main content that takes all of screen’s height except the header size:

<style>
    body {
        font-size: clamp(1.5rem, 2vw, 2rem);
        text-align: center;
        margin: 0;
        padding: 0;
    }

    header {
        width: 100%;
        height: 4rem;
        background-color: darkseagreen;
    }

    main {
        width: 100%;
        height: calc(100vh - 4rem);
        background-color: #d1d5db;
    }
</style>

<body>
    <header>Header here</header>
    <main>Content here</main>
</body>
Enter fullscreen mode Exit fullscreen mode

Using calc() function to calculate a part of a CSS property

The calc() function can be used to calculate a result for a part of the CSS property. For example you can create a flexible background position:

.content {
    background-position: calc(100% - 500px) center;
}
Enter fullscreen mode Exit fullscreen mode

This style adds a margin for background image horizontally while keeping it centered vertically.

The same way you can dynamically calculate parts of margin or padding:

.content {
    margin: 20px calc(2rem + 10px);
    padding: 10px calc(2rem + 10px) 10px calc(1rem + 5px);
}
Enter fullscreen mode Exit fullscreen mode

Using calc() inside other functions

A very cool feature of calc() function is that it can be nested within other functions for more complex calculations. We can use calc() inside a clamp() function to create a responsive font size for different screen sizes:

body {
    font-size: clamp(16px, calc(1vw + 1em), 24px);
}
Enter fullscreen mode Exit fullscreen mode

In this example, clamp() is used to ensure the font size never goes below 16px or above 24px. The middle value uses calc() to add 1em to 1vw, offering a flexible scaling effect on different screen sizes.

clamp() used together with calc() allows to create a really complex calculations for a more responsive design.

Interesting fact: calc() can be nested inside another calc() function.

Using calc() to perform math calculations

A calc() function can be used as a more elegant way to express math calculations:

.content {
    width: calc(100% / 9);
}
Enter fullscreen mode Exit fullscreen mode

This is much more readable than expressing the width like: 11,11111111111111%;

Using calc() CSS Function for Custom Properties

Custom CSS properties, also called CSS variables, are a powerful tool for building web designs. Great news, that we can use calc() function for custom properties.

Typically custom CSS properties are declared at the root level for global accessibility but can be scoped to individual selectors as needed. They are defined as follows:

:root {
    --main-color: #374151;
    --padding: 16px;
}
Enter fullscreen mode Exit fullscreen mode

These properties can then be reused throughout the stylesheet. For example, we can define a color as a variable in one place and reuse it in different CSS styles throughout different pages.

We can use calc() function for custom CSS properties:

:root {
    --base-font-size: 18px;
}

.content {
    font-size: calc(var(--base-font-size) + 1vw);
}
Enter fullscreen mode Exit fullscreen mode

Here we define a property with base font-size and adjust it based on the viewport width. To access a CSS variable's name - the var function is used, that accepts a single parameter - name of the variable.

Limitations When Using calc() CSS Function

The Importance of Whitespaces

One of the most common pitfalls when using calc() is the handling of whitespace around operators. In calc() expressions, the addition (+) and subtraction (-) operators must be surrounded by whitespace to be recognized as operators. Without proper whitespaces, these operators could be interpreted as part of a number (e.g., positive or negative numbers) and result in a syntax error.

Correct Whitespace Usage:

.content {
    width: calc(100% - 50px);
}
Enter fullscreen mode Exit fullscreen mode

Incorrect Whitespace Usage:

.content {
    width: calc(100%-50px);
}
Enter fullscreen mode Exit fullscreen mode

Also a negative number can be used for numbers in the expression:

.content {
    width: calc(100% - -50px);
}
Enter fullscreen mode Exit fullscreen mode

For the multiplication (*), and division (/) operators it is not necessary to use whitespaces. But it is considered a good practice to include whitespace around all arithmetic operators to improve code readability.

Addition (+) and Subtraction (-) Requirements

Both addition (+) and subtraction (-) operators require all numbers in the expression to have CSS units (px, vw, vh, %, em, rem, etc) specified.

Correct usage:

.content {
    width: calc(100% - 50px);
    font-size: calc(2vw + 5px);
    margin: calc(2rem + 10px);
}
Enter fullscreen mode Exit fullscreen mode

Incorrect usage:

.content {
    width: calc(100% - 5);
    font-size: calc(2vw + 10);
    margin: calc(2rem + 10px + 5);
}
Enter fullscreen mode Exit fullscreen mode

Multiplication (*) and Division (/) Requirements

Multiplication (*) operator requires one of the numbers in the expression to be unitless. Division*(/)* operator requires the second number in the expression to be unitless.

Correct usage:

.content {
    font-size: calc(1.5 * 16px);
    width: calc(100% / 9);
}
Enter fullscreen mode Exit fullscreen mode

Incorrect usage:

.content {
    font-size: calc(1.5% * 16px);
    width: calc(100% / 9px);
    height: calc(100 / 9px);
}
Enter fullscreen mode Exit fullscreen mode

Usage in Media Queries

Unfortunately, calc() CSS functions can't be used in media queries, for example:

@media (min-width: calc(500px + 10vw)) {
    /* This will not work */
}
Enter fullscreen mode Exit fullscreen mode

Summary

calc() CSS function allows to perform calculations to determine CSS property values. It supports basic arithmetic operations: addition, subtraction, multiplication, and division - across different CSS units, such as pixels, percentages, viewport dimensions, em, rem, etc.

This function really helps in creating flexible responsive designs by dynamically adjusting needed properties.

Despite its power, it’s essential to use calc with an understanding of its limitations:

  • mandatory whitespace around arithmetic operators
  • nuances with CSS units and unitless numbers for different arithmetic operators
  • calc can’t be used in media queries

This feature is highly supported by all modern web browsers:

CSS math functions min(), max() and clamp() (97% support)

Hope you find this blog post useful. Happy coding!

Originally published at https://antondevtips.com.

After reading the post consider the following:

  • Subscribe to receive newsletters with the latest blog posts
  • Download the source code for this post from my github (available for my sponsors on BuyMeACoffee and Patreon)

If you like my content —  consider supporting me

Unlock exclusive access to the source code from the blog posts by joining my Patreon and Buy Me A Coffee communities!

Top comments (0)