CSS Calc Function
The calc() function lets you perform math directly inside CSS property values. It mixes different unit types in a single expression — something that regular CSS values cannot do. Instead of calculating pixel values manually, you let the browser do the math at render time.
Why calc() Exists
DIAGRAM — The problem calc() solves:
You want a sidebar to be exactly 300px wide
and the main content to fill the rest.
Without calc():
You guess pixel values, recalculate for each screen size,
or use JavaScript. Complex and error-prone.
With calc():
.main { width: calc(100% - 300px); }
Browser calculates the right value on every screen automatically.
Basic Syntax
property: calc(expression);
The expression uses standard math operators:
+addition-subtraction*multiplication/division
Important: The + and - operators must have a space on each side. This is required — calc(100%-300px) is invalid, calc(100% - 300px) is correct.
Mixing Units
This is the superpower of calc(). You can mix percentages, pixels, rem, vh, and other units in one expression.
/* Percentage minus pixels */
.main-content {
width: calc(100% - 280px);
}
/* Viewport height minus a fixed header */
.page-body {
min-height: calc(100vh - 64px);
}
/* Relative to root font size */
.card {
padding: calc(1rem + 8px);
}
Common Use Cases
Sidebar + Main Layout
DIAGRAM — Sidebar + Content layout:
Page: 100% wide
├── Sidebar: 260px (fixed)
└── Main: rest of the space
.sidebar {
width: 260px;
float: left;
}
.main {
width: calc(100% - 260px);
float: left;
}
On a 1000px screen: main = calc(1000px - 260px) = 740px
On a 800px screen: main = calc(800px - 260px) = 540px
Automatically adapts!
Full-Viewport Page Minus Header
header {
height: 60px;
}
main {
min-height: calc(100vh - 60px);
/* Fills the visible screen below the header */
}
DIAGRAM — Viewport minus header:
┌────────────────────────┐ ─────
│ Header (60px) │ ↑
├────────────────────────┤ │ 100vh
│ │ │
│ Main content │ │
│ (calc(100vh - 60px)) │ ↓
└────────────────────────┘ ─────
Centered Element with Offset
.tooltip {
position: absolute;
left: calc(50% - 80px); /* centered, minus half of tooltip width */
width: 160px;
}
Equal Columns with Gap
/* Three equal columns with 20px gaps between them */
/* (2 gaps total between 3 columns) */
.col {
width: calc((100% - 40px) / 3);
/* 40px = 20px gap × 2 */
}
Fluid Typography
h1 {
font-size: calc(1.5rem + 2vw);
/* Combines a base size with a viewport-relative boost */
/* Never smaller than 1.5rem, grows as viewport widens */
}
DIAGRAM — Fluid font size with calc():
Viewport 320px: font-size = 1.5rem + 6.4px ≈ 30px
Viewport 768px: font-size = 1.5rem + 15.4px ≈ 39px
Viewport 1200px: font-size = 1.5rem + 24px ≈ 48px
Smoothly grows without media query breakpoints!
Negative Space / Bleed
/* Make an element bleed outside its container by 24px on each side */
.full-bleed {
width: calc(100% + 48px);
margin-left: -24px;
}
Using calc() with CSS Variables
calc() and CSS custom properties work together naturally.
:root {
--header-height: 64px;
--sidebar-width: 280px;
--gap: 24px;
}
.page-content {
min-height: calc(100vh - var(--header-height));
width: calc(100% - var(--sidebar-width) - var(--gap));
}
Nested calc()
You can nest calc() inside itself, though modern browsers also accept plain arithmetic without nesting.
.box {
width: calc(calc(100% - 60px) / 3);
/* Same result, modern syntax (no nesting needed): */
width: calc((100% - 60px) / 3);
}
calc() with Multiplication and Division
For * and /, at least one value must be a unitless number.
/* Valid */
width: calc(50% * 2); /* 100% */
width: calc(100px / 4); /* 25px */
width: calc(2 * 100px); /* 200px */
/* Invalid */
width: calc(50% * 20%); /* Two percentages cannot be multiplied */
Other Math Functions (Modern CSS)
CSS has added several related math functions. They work alongside calc().
min(a, b)— uses the smaller value. Great for capping widths.max(a, b)— uses the larger value. Great for setting minimums.clamp(min, preferred, max)— constrains a value between a minimum and maximum.
/* Width is at most 600px, but responsive below that */
width: min(600px, 100%);
/* Font size between 1rem and 2rem, ideally 2.5vw */
font-size: clamp(1rem, 2.5vw, 2rem);
DIAGRAM — clamp(1rem, 2.5vw, 2rem):
Viewport 320px: 2.5vw = 8px → clamp gives 1rem (16px) ← minimum
Viewport 800px: 2.5vw = 20px → clamp gives 1.25rem (20px) ← in range
Viewport 1200px: 2.5vw = 30px → clamp gives 2rem (32px) ← maximum
Text grows smoothly and is never too small or too large.
When to Use calc()
| Situation | Use calc()? |
|---|---|
| Mix percentage and px | Yes — only calc() can do this |
| Viewport minus fixed header | Yes — calc(100vh - 64px) |
| Fluid font sizing | Yes — or use clamp() |
| Equal columns with gap | Yes — or use CSS Grid with gap |
| Convert units (px to rem) | No — use the unit directly |
| Simple single-unit math | No — just write the value |
calc() turns the browser into your calculator. It keeps your CSS readable — you see the intent ("100% minus the sidebar") rather than a magic number — and it adapts automatically as the context changes.
