1838

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?

Ninjakannon
  • 3,751
  • 7
  • 53
  • 76
GJK
  • 37,023
  • 8
  • 55
  • 74
  • 10
    possible duplicate of [Usa a Variable in a Mixin](http://stackoverflow.com/questions/16660985/usa-a-variable-in-a-mixin) – cimmanon Jul 31 '13 at 22:36
  • 23
    @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 Jul 18 '16 at 16:05
  • @cimmanon Well, the other way around now, since this question got way more popular. – General Grievance Feb 18 '22 at 18:23

6 Answers6

3444

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
Christoph
  • 50,121
  • 21
  • 99
  • 128
sam
  • 40,318
  • 2
  • 41
  • 37
  • 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 Jun 21 '18 at 03:18
  • 1
    Many thanks! I was about to go the css route with `calc(100% - var(--body_padding))` – Sylar May 14 '19 at 05:19
  • @leachim Sass interpolation is evaluated by the Sass compiler, not by the browser. – Chris Peters Nov 16 '21 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](https://sass-lang.com/documentation/values/numbers#units) – noxter Mar 13 '23 at 09:04
  • 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 https://sass-lang.com/documentation/values/calculations. – Klofi Apr 03 '23 at 08:58
140

To use $variables inside your calc() of the height property:

HTML:

<div></div>

SCSS:

$a: 4em;

div {
  height: calc(#{$a} + 7px);
  background: #e53b2c;
}
DA SILVA MARLY Joao
  • 1,409
  • 1
  • 7
  • 5
  • 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. – 2b77bee6-5445-4c77-b1eb-4df3e5 May 03 '19 at 15:15
  • 9
    This is definitely a clearer answer than the accepted. 'Interpolate:' meant nothing to me. – Jacques Mathieu Aug 05 '19 at 16:15
  • 9
    @JacquesMathieu https://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... – Alberto Chiesa Aug 21 '19 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. – Jacques Mathieu Aug 31 '19 at 18:48
  • I was stuck on this for more than 1 hour. – hamzaali Aug 13 '20 at 12:54
  • It's (now) easier to understand because this is written in the scss format vs sass format which is now for more common than it was when this was answered. (I actually don't know if it existed when this was asked, but if it didn't it was within roughly a year). I saw sass and immediately skipped over the accepted answer until I saw this scss answer. – claudekennilol Jan 06 '21 at 23:16
58

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.

Ryan Taylor
  • 12,559
  • 2
  • 39
  • 34
Udit
  • 659
  • 6
  • 2
  • 1
    also an additional space after `calc` ist not allowed. `calc (#{$a} + 7px)` won't work out. – Entara Aug 12 '20 at 08:16
  • The person above used spaces correctly, so this doesn't really answer their question, but it answered mine. Thank you! – Jameela Huq Sep 09 '20 at 00: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 – Manish Rana Feb 12 '21 at 06:25
  • care, this does not work in IE and Edge HTML – leachim Oct 29 '21 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);
}
Serkan KONAKCI
  • 1,100
  • 11
  • 16
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/

Carl L.D.
  • 89
  • 1
  • 6
-7

Try this:

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

body{
   @include heightBox(100% - 25%);
   box-sizing: border-box
   padding:10px;
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Mas Hary
  • 96
  • 3