calc() does arithmetic inside a CSS value. Its power is that it can mix units, which nothing else can do.
<style>
.parent { width: 100%; background: #f4f9fc; padding: 6px; box-sizing: border-box; }
.sidebar { width: 100px; background: #1a5276; color: #fff; padding: 8px; display: inline-block; vertical-align: top; box-sizing: border-box; }
.main { width: calc(100% - 100px); background: #d94a00; color: #fff; padding: 8px; display: inline-block; vertical-align: top; box-sizing: border-box; }
</style>
<div class="parent"><div class="sidebar">100px</div><div class="main">calc(100% - 100px)</div></div>
The main area takes “everything except 100px”. Percentages and pixels cannot be added in any other way.
The rules
- Use
+,-,*and/. - Spaces are required around
+and-:calc(100% - 20px)works,calc(100%-20px)does not. - For
and/, at least one side must be a plain number:calc(2rem 3),calc(100% / 3). - You can nest and use parentheses:
calc((100% - 2rem) / 3). - Variables work inside:
calc(var(--gap) * 2).
Useful examples
/* A full-height section under a 64px header */
.content { min-height: calc(100vh - 64px); }
/* Three columns with two 16px gaps */
.col { width: calc((100% - 32px) / 3); }
/* A font size that grows with the viewport but has a base */
h1 { font-size: calc(1.5rem + 2vw); }
/* Spacing as a multiple of a variable */
.card { padding: calc(var(--space) * 2); }
When you do not need it
If flexbox or grid can do the job, such as sharing columns, they are usually simpler. calc() shines for the odd sizes: “viewport minus a fixed header” and similar.
Missing spaces
calc(100%-20px) is invalid, and the browser silently ignores the whole declaration. If a calc() has no effect, check the spaces first.