1865

I'm trying to use the calc() function in a Sass stylesheet, but I'm having some issues. Here's my code:

$body_padding: 50px

body
    padding-top: $body_padding
    height: calc(100% - $body_padding)

If I use the literal 50px instead of my body_padding variable, I get exactly what I want. However, when I switch to the variable, this is the output:

body {
    padding-top: 50px;
    height: calc(100% - $body_padding);
}

How can I get Sass to recognize that it needs to replace the variable within the calc function?

3
  • 10
    possible duplicate of Usa a Variable in a Mixin
    – cimmanon
    Commented Jul 31, 2013 at 22:36
  • 24
    @user3705055 You do need calc as Sass can't calculate 100% - 50px as the units are different. This can only be calculated by the browser, once it knows how big the container is in order to convert 100% to px before adding the values. This is the exact reason why calc exists.
    – Mog0
    Commented Jul 18, 2016 at 16:05
  • @cimmanon Well, the other way around now, since this question got way more popular. Commented Feb 18, 2022 at 18:23

6 Answers 6

3470

Interpolate:

body
    height: calc(100% - #{$body_padding})

For this case, border-box would also suffice:

body
    box-sizing: border-box
    height: 100%
    padding-top: $body_padding
6
  • 5
    box-sizing: border-box; would be the ideal way to go, in my opinion, of course. In general, the box sizing model should make t
    – brandito
    Commented Jun 21, 2018 at 3:18
  • 1
    Many thanks! I was about to go the css route with calc(100% - var(--body_padding))
    – Sylar
    Commented May 14, 2019 at 5:19
  • @leachim Sass interpolation is evaluated by the Sass compiler, not by the browser. Commented Nov 16, 2021 at 21:44
  • Even if it is OP's question, it’s almost always a bad idea to use interpolation with numbers. Interpolation returns unquoted strings that can’t be used for any further math, and it avoids Sass’s built-in safeguards to ensure that units are used correctly. This case should be better handled with sass' units
    – noxter
    Commented Mar 13, 2023 at 9:04
  • 2
    Note interpolation is no longer needed since sass 1.40.0 per changelog entry "Sass variables and functions can now be used in calc() expressions.". So you can simple use height: calc(100% - $body_padding). Using the interpolation in calc is now actually discouraged by sass documentation at sass-lang.com/documentation/values/calculations.
    – Klofi
    Commented Apr 3, 2023 at 8:58
145

To use $variables in calc() for any SCSS property:

HTML:

<div></div>

SCSS:

$a: 4em;

div {
  height: calc(#{$a} + 7px);
  background: #e53b2c;
}
6
  • 10
    For some reason, I find this answer clearer. I don't do a lot of scss work, so this was "plainer" and easier for me to understand. Commented May 3, 2019 at 15:15
  • 9
    This is definitely a clearer answer than the accepted. 'Interpolate:' meant nothing to me. Commented Aug 5, 2019 at 16:15
  • 9
    @JacquesMathieu sass-lang.com/documentation/interpolation - If it doesn't mean anything to you and it's an answer with so many votes, probably you should understand what the fuss is about. Just my two cents... Commented Aug 21, 2019 at 22:04
  • 2
    @A. Chiesa sure, that defines interpolation. However the OP and I did not know of interpolation in SASS, otherwise this question would have never been asked. Thus just stating a word one may have never heard before without a definition or any pretense does not aid in creating an all inclusive answer. That link is certainly helpful though. Would have been nice to see that on the accepted answer. Commented Aug 31, 2019 at 18:48
  • I was stuck on this for more than 1 hour.
    – hamzaali
    Commented Aug 13, 2020 at 12:54
60

Even though its not directly related. But I found that the CALC code won't work if you do not put spaces properly.

So this did not work for me calc(#{$a}+7px)

But this worked calc(#{$a} + 7px)

Took me sometime to figure this out.

4
  • 1
    also an additional space after calc ist not allowed. calc (#{$a} + 7px) won't work out.
    – Entara
    Commented Aug 12, 2020 at 8:16
  • The person above used spaces correctly, so this doesn't really answer their question, but it answered mine. Thank you! Commented Sep 9, 2020 at 0:38
  • Yes this worked for me. I tried height:calc(100%-95px); (i.e without proper space. ) at first and it didn't work. But with proper spacing it worked without interpolation Commented Feb 12, 2021 at 6:25
  • care, this does not work in IE and Edge HTML
    – leachim
    Commented Oct 29, 2021 at 13:03
7

I have tried this then i fixed my issue. It will calculate all media-breakpoint automatically by given rate (base-size/rate-size)


$base-size: 16;
$rate-size-xl: 24;

    // set default size for all cases;
    :root {
      --size: #{$base-size};
    }

    // if it's smaller then LG it will set size rate to 16/16;
    // example: if size set to 14px, it will be 14px * 16 / 16 = 14px
    @include media-breakpoint-down(lg) {
      :root {
        --size: #{$base-size};
      }
    }

    // if it is bigger then XL it will set size rate to 24/16;
    // example: if size set to 14px, it will be 14px * 24 / 16 = 21px
    @include media-breakpoint-up(xl) {
      :root {
        --size: #{$rate-size-xl};
      }
    }

@function size($px) {
   @return calc(#{$px} / $base-size * var(--size));
}

div {
  font-size: size(14px);
  width: size(150px);
}
2

Here is a really simple solution using SASS/SCSS and a math formula style:

/* frame circle */
.container {
    position: relative;
    border-radius: 50%;
    background-color: white;
    overflow: hidden;
    width: 400px;
    height: 400px; }

/* circle sectors */
.menu-frame-sector {
    position: absolute;
    width: 50%;
    height: 50%;
    z-index: 10000;
    transform-origin: 100% 100%;
  }

$sector_count: 8;
$sector_width: 360deg / $sector_count;

.sec0 {
    transform: rotate(0 * $sector_width) skew($sector_width);
    background-color: red; }
.sec1 {
    transform: rotate(1 * $sector_width) skew($sector_width);
    background-color: blue; }
.sec2 {
    transform: rotate(2 * $sector_width) skew($sector_width);
    background-color: red; }
.sec3 {
    transform: rotate(3 * $sector_width) skew($sector_width);
    background-color: blue; }
.sec4 {
    transform: rotate(4 * $sector_width) skew($sector_width);
    background-color: red; }
.sec5 {
    transform: rotate(5 * $sector_width) skew($sector_width);
    background-color: blue; }
.sec6 {
    transform: rotate(6 * $sector_width) skew($sector_width);
    background-color: red; }
.sec7 {
    transform: rotate(7 * $sector_width) skew($sector_width);
    background-color: blue; }

To conclude, I strongly suggest you to understand transform-origin, rotate() and skew():

https://tympanus.net/codrops/2013/08/09/building-a-circular-navigation-with-css-transforms/

0
-7

Try this:

@mixin heightBox($body_padding){
   height: calc(100% - $body_padding);
}

body{
   @include heightBox(100% - 25%);
   box-sizing: border-box
   padding:10px;
}
1
  • 2
    It won't work by the same reason as the code in the question.
    – Qwertiy
    Commented Aug 3, 2021 at 18:24

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.