Magnus
Magnus

Reputation: 7821

SCSS: Inverting/Negating Variable Based on calc()

I am using SCSS and wanted to specify a variable at top that is based on a sum of a px and a rem value.

I understand that it is not possible to combine unit types in SCSS variables, so instead I use calc():

$navbar-top: calc(40px + 1 rem);

Further down in the style sheet, I wanted to include a negated version of $navbar-top.

I tried both these, with no success:

(-$navbar-top)
-#{$navbar-top}

Any idea how I can negate the SCSS variable, without having to declare a new variable, or writing calc again throughout the CSS.

Thanks.


EDIT


EDIT 2: SCSS SOLUTION BASED ON TEMANI'S ANSWER BELOW

Declare the necessary variables at top, including a "negator" (-1):

$navbar-top: calc(40px + 1rem);
$neg: -1;

Then, the variable can be used throughout (negated or not), like this:

/* Non-negated */
margin: $navbar-top 0 0;

/* Negated */
margin: calc(#{$neg} * #{$navbar-top}) 0 0;

The negated version above will compile to the following CSS:

margin: calc(-1 * calc(40px + 1rem)) 0 0;

Upvotes: 6

Views: 3410

Answers (2)

Temani Afif
Temani Afif

Reputation: 272842

Since calc is not a usual value you cannot simply append a - sign on it to obtain the negative value.

An idea would be to consider another parameter to control the sign. Here is an idea using pure CSS and CSS variable without the need of another calc()

.box {
  margin-top: calc( var(--s,1)*(40px + 1rem));
  height:100px;
  background:rgba(255,0,0,0.5);
}
<div class="box"></div>
<div class="box" style="--s:-1"></div>

You can define the negative value using class

.box {
  margin-top: calc( var(--s,1)*(40px + 1rem));
  height:100px;
  background:rgba(255,0,0,0.5);
}
.neg {
  --s:-1;
}
<div class="box"></div>
<div class="box neg"></div>

UPDATE

You may also consider the expression using variables:

:root {
  --exp:(40px + 1rem);
}

.box {
  margin-top: calc( var(--s,1)*var(--exp));
  height:100px;
  background:rgba(255,0,0,0.5);
}
<div class="box"></div>
<div class="box" style="--s:-1"></div>

Upvotes: 3

Ari
Ari

Reputation: 1703

You can use an @function instead of a variable

DEMO

// The argument is defaulted to true,
// so you only need to pass an argument if you want a negative number
@function navbar-top($isPositive: true) {
    @if $isPositive { @return calc(40px + 1rem); }
    @else {@return calc((40px + 1rem) * -1); }
}

// Calling the function with the default value
.normal { margin-top: navbar-top(); }

// Calling the function with negative value
.negative { margin-top: navbar-top(false); }

Upvotes: 2

Related Questions