CSS's calc() function lets you perform math directly inside a property value — and crucially, it lets you mix different units in the same calculation, something that isn't possible any other way in CSS. Need a sidebar that's exactly 250 pixels wide and a main content area that fills "everything else"? calc() is the tool built for exactly that.
Basic Syntax
calc() supports addition, subtraction, multiplication, and division. The one syntax rule that trips people up: there must be a space on both sides of + and - (not * or /), or the browser won't parse it correctly.
.box {
/* Correct — spaces around the minus sign */
width: calc(100% - 40px);
}
.bad-box {
/* Invalid — browsers will ignore this rule entirely */
width: calc(100%-40px);
}
Mixing Units
.full-bleed-minus-gutters {
width: calc(100vw - 2rem);
}
.header-offset {
/* leaves room for a fixed 60px header */
min-height: calc(100vh - 60px);
}
Neither of these could be written without calc() — there's no single unit that means "the full viewport width minus a fixed amount of rem-based spacing." calc() resolves each unit to pixels internally and does the subtraction for you.
A Practical Sidebar Layout
<div class="layout">
<aside class="sidebar">Sidebar</aside>
<main class="content">Main content</main>
</div>
.layout {
display: flex;
}
.sidebar {
width: 250px;
flex-shrink: 0;
}
.content {
width: calc(100% - 250px);
padding: 1rem;
}
The sidebar stays a fixed 250px regardless of screen size, and the main content area automatically fills whatever width remains. (In practice, flex: 1 on .content would achieve the same layout without any calc() at all — a good reminder that calc() shines most when no layout mode already solves the problem for you, such as mixing a fixed value with a viewport unit.)
Nesting and CSS Variables
calc() also works seamlessly with custom properties, which is one of the most common real-world combinations you'll see:
:root {
--header-height: 64px;
}
.page-body {
min-height: calc(100vh - var(--header-height));
}
This keeps the header height defined in exactly one place — change --header-height and every calc() expression referencing it updates automatically. For layouts where you want a value to scale smoothly between two bounds instead of being a fixed offset, the newer clamp(), min(), and max() functions are often an even better fit.
