Question
I am trying to use the CSS calc() function in a Sass stylesheet, but the Sass variable is not being replaced inside the calc() expression.
Here is the code:
$body_padding: 50px
body
padding-top: $body_padding
height: calc(100% - $body_padding)
If I write the value directly as 50px, the output is correct. But when I use the variable, Sass produces this CSS:
body {
padding-top: 50px;
height: calc(100% - $body_padding);
}
How can I make Sass replace the variable correctly inside the calc() function?
Short Answer
By the end of this page, you will understand why Sass sometimes leaves variables untouched inside calc(), how interpolation solves that problem, and how to write calc() expressions that compile correctly and stay valid CSS.
Concept
Sass variables are normally replaced during compilation. For example, if $spacing is 20px, Sass usually turns margin-top: $spacing into margin-top: 20px.
However, calc() is a special case because it is also a native CSS function. Sass sometimes treats parts of a calc() expression as plain CSS to preserve the browser's own calculation rules. When that happens, a Sass variable written directly inside the expression may not always be evaluated the way you expect.
The common solution is interpolation, written as #{...}. Interpolation tells Sass: “insert the final value here as text before generating the CSS.”
Example:
height: calc(100% - #{$body_padding})
This compiles to:
height: calc(100% - 50px)
Why this matters:
calc()is widely used for layout calculations.- Sass variables help keep spacing and sizing consistent.
- Combining them correctly makes stylesheets easier to maintain.
- If you misunderstand how Sass parses CSS functions, you can end up with broken output or confusing bugs.
In short: when Sass does not evaluate a variable inside , use interpolation to explicitly inject the value.
Mental Model
Think of Sass as a template engine that fills in blanks before the browser sees the CSS.
- A Sass variable is like a labeled sticky note:
$body_padding = 50px - A normal property such as
padding-top: $body_paddingis easy for Sass to fill in. - But
calc()is like a sealed formula box that the browser wants to evaluate later. - Sometimes Sass leaves the contents alone unless you explicitly open the box and place the value inside.
Interpolation #{...} is that explicit instruction.
So this:
calc(100% - #{$body_padding})
means:
“Before you output the CSS, take the value stored in
$body_paddingand paste it into this exact spot.”
Syntax and Examples
Core syntax
Use interpolation when inserting a Sass variable into calc():
$body_padding: 50px
body
height: calc(100% - #{$body_padding})
Compiled CSS:
body {
height: calc(100% - 50px);
}
Another example
$sidebar-width: 250px;
.main {
width: calc(100% - #{$sidebar-width});
}
Compiled CSS:
.main {
width: calc(100% - 250px);
}
Why interpolation works
#{...} tells Sass to resolve the variable and insert its value directly into the final CSS string.
Example with multiple values
: ;
: ;
{
: ( - #{} - #{});
}
Step by Step Execution
Consider this Sass code:
$body_padding: 50px
body
padding-top: $body_padding
height: calc(100% - #{$body_padding})
Here is what happens step by step:
-
Sass reads the variable declaration:
$body_paddingstores50px
-
Sass processes
padding-top: $body_padding- This is a normal property value
- Sass replaces
$body_paddingwith50px
-
Sass processes
height: calc(100% - #{$body_padding})- It sees interpolation:
#{$body_padding} - It resolves the variable value to
50px - It inserts that text into the expression
- It sees interpolation:
-
The final CSS becomes:
body {
padding-top: 50px;
height: calc(100% - 50px);
}
Real World Use Cases
calc() with Sass variables is useful whenever part of a layout is fixed and part is flexible.
Common scenarios
-
Full-height content below a header
$header-height: 64px; .page-content { min-height: calc(100vh - #{$header-height}); } -
Main area next to a fixed sidebar
$sidebar-width: 280px; .main { width: calc(100% - #{$sidebar-width}); } -
Responsive cards with a shared gap
$gap: 24px; .card { width: calc(50% - #{$gap}); } -
Viewport-based spacing with design tokens
: ; { : ( - #{}); }
Real Codebase Usage
In real projects, developers usually combine Sass variables in calc() with reusable design values and layout patterns.
Common patterns
Design tokens
Teams often store spacing and size values in variables:
$nav-height: 72px;
$container-gap: 24px;
Then use them across components:
.layout {
min-height: calc(100vh - #{$nav-height});
padding: calc(#{$container-gap} / 2);
}
Configuration-driven layouts
A sidebar width or header height may be defined once and reused everywhere:
$sidebar-width: 260px;
.content {
margin-left: $sidebar-width;
width: calc(100% - #{$sidebar-width});
}
Guarding consistency
Using variables prevents magic numbers from being repeated:
Common Mistakes
1. Using a variable directly when interpolation is needed
Broken:
$body_padding: 50px
body
height: calc(100% - $body_padding)
Possible output:
height: calc(100% - $body_padding);
Fixed:
$body_padding: 50px
body
height: calc(100% - #{$body_padding})
2. Forgetting units
Broken:
$header-height: 50;
.main {
height: calc(100vh - #{$header-height});
}
This becomes calc(100vh - 50), which is often invalid for layout sizing.
Fixed:
$header-height: 50px;
3. Mixing incompatible values
Broken idea:
$color: red;
.box {
: ( - #{});
}
Comparisons
Sass variable replacement vs interpolation
| Approach | Example | When to use it | Result |
|---|---|---|---|
| Normal variable usage | padding: $gap; | Standard property values | Sass replaces the variable normally |
| Interpolation | calc(100% - #{$gap}) | When inserting a value into a CSS expression or string-like context | Sass injects the resolved value |
Sass math vs CSS calc()
| Feature | Sass math | CSS calc() |
|---|---|---|
| When it runs | During compilation | In the browser |
| Example |
Cheat Sheet
Quick reference
Define a variable
$body_padding: 50px;
Use it normally
padding-top: $body_padding;
Use it inside calc()
height: calc(100% - #{$body_padding});
Compiled output
height: calc(100% - 50px);
Rule of thumb
- Use
$variablefor normal property values - Use
#{$variable}when Sass needs explicit interpolation inside a CSS expression
Common pattern
$header-height: 64px;
$content-gap: 24px;
{
: ( - #{});
: ( - #{});
}
FAQ
Why does Sass not replace my variable inside calc()?
Because calc() is a native CSS function, and Sass may preserve its contents instead of evaluating the variable directly. Interpolation tells Sass to insert the value explicitly.
What is the correct syntax for a Sass variable in calc()?
Use interpolation:
height: calc(100% - #{$body_padding});
Can I use Sass math instead of calc()?
Sometimes, yes, if the whole calculation can be resolved at compile time. But if you are mixing values like % and px, calc() is usually necessary because the browser must compute it during layout.
Does this work in both .sass and .scss syntax?
Yes. The idea is the same. Only the file syntax differs.
Should I always use interpolation with Sass variables?
No. For normal properties, use the variable directly. Use interpolation when Sass needs help inserting the value into a CSS expression or string-like context.
Can I put multiple Sass variables in one ?
Mini Project
Description
Build a simple page layout with a fixed header and a content section that fills the remaining viewport height. This demonstrates a very common reason for combining Sass variables with CSS calc(): one part of the layout has a fixed size, while another must adapt dynamically.
Goal
Create a layout where the content area automatically subtracts the header height using a Sass variable inside calc().
Requirements
- Define a Sass variable for the header height.
- Apply that variable to the header height.
- Make the main content height equal to the viewport height minus the header height.
- Use the correct Sass syntax so the compiled CSS contains a valid
calc()expression.
Keep learning
Related questions
CSS Font Scaling Relative to Container Size: %, em, rem, vw, and Responsive Text
Learn how CSS font scaling really works and how to make text responsive using %, em, rem, vw, clamp(), and media queries.
CSS Parent Selector Explained: Selecting a Parent <li> from an <a>
Learn whether CSS has a parent selector, how :has() works, and practical alternatives for styling a parent li from a child anchor.
CSS Previous Sibling Selector: What Exists and How to Work Around It
Learn whether CSS has a previous sibling selector, why it does not, and practical ways to style earlier elements using CSS alternatives.