126

I have a couple of scss selectors where I use the same amount positive and negative, as in:

padding: 0 15px 15px;
margin: 0 -15px 20px -15px;

I'd prefer to use a variable for all the 15px amounts, but this does not work:

$pad: 15px;
padding: 0 $pad $pad;
margin: 0 -$pad 20px -$pad;

The margin amounts convert to positive numbers. Am I missing something?

Steve
  • 13,564
  • 28
  • 118
  • 212

5 Answers5

243

Try it like this

margin: 0 (-$pad) 20px (-$pad);
Zoltan Toth
  • 46,038
  • 11
  • 115
  • 133
  • 2
    Automatically tried this approach - seems not to be working when using in calc function. Edit: Seems like you don't need to use parentheses when using calc, but you do need to interpolate http://stackoverflow.com/questions/17982111/sass-variable-in-css-calc-function – Kevin Mar 20 '17 at 15:38
48

A more sane solution according to sass guidelines would be to interpolate variables like the following example:

margin: 0 -#{$pad} 20px -#{$pad};

An example: https://www.sassmeister.com/gist/c9c0208ada0eb1fdd63ae47830917293

Vangel Tzo
  • 8,075
  • 3
  • 25
  • 31
  • @Green You can always check the example link: https://www.sassmeister.com/gist/c9c0208ada0eb1fdd63ae47830917293 – Vangel Tzo Oct 21 '19 at 20:28
  • This is better than the accepted answer because it works when using a mixin inside it also :) – OZZIE Sep 15 '21 at 10:20
7

I'm adding my two-penneth after considering the two previous answers, but then reading this (emphasis mine):

You should especially avoid using interpolation like #{$number}px. This doesn’t actually create a number! It creates an unquoted string that looks like a number, but won’t work with any number operations or functions. Try to make your math unit-clean so that $number already has the unit px, or write $number * 1px.

Source

Therefore I believe the correct way would be as follows, which preserves the mathematical abilities of SASS/SCSS:

$pad: 15px;
padding: 0 $pad $pad;
margin: 0 $pad*-1 20px $pad*-1;
EvilDr
  • 8,131
  • 11
  • 66
  • 121
  • 2
    At first glance, it seems to be nit-picking (your answer), but on second glance it really is the better answer. After all, if the variable does become a negative variable the answer becomes positive! $pad: -2rem; ... margin: 0 -#{$pad}; // becomes margin: 0 --2rem; margin: 0 $pad*-1; // becomes margin: 0 2rem; – Fnordius Jun 23 '20 at 14:47
  • this is a novel solution but I disagree that it's the "correct" way - do you think it's even better than this similar solution? `margin: 0 0 - $pad 20px 0 - $pad;` – Jon z Mar 09 '22 at 15:13
2

create a function

@function neg($val) {
  @return $val * -1
};

then I use it like this

$gutter: 30px;

.header {
  margin: $gutter neg($gutter);
}
Bouh
  • 1,212
  • 2
  • 8
  • 22
1

The official sass guides suggest a similar solution to the (currently) highest voted answer - instead of wrapping the minus-sign inside the parens, put it outside, e.g.

$pad: 15px;
padding: 0 $pad $pad;
margin: 0 -($pad) 20px -($pad);

source: https://sass-lang.com/documentation/operators/numeric#unary-operators

and per #comment-72915126 you would want to interpolate the sass value when it appears inside a css calc function:

margin: calc(#{-$pad} - 10px);

strangely, the parens are no longer required - perhaps the string interpolation acts in a similar way to wrapping it in parens?

(I'm using prettier@2.3 and dart-sass@1.49)

Jon z
  • 3,744
  • 1
  • 27
  • 20