0

I have *.scss file in an Angular 7 project.

After compiling it, the compiler adds unwanted whitespace to the css, which leads to wrong results in the UI.

To reproduce the error go to...

https://www.sassmeister.com/

...copy and paste the following code.

$color-background-default:  white;
$color-foreground-default:  black;

$color-background-disabled: #d3d3d3;
$color-foreground-disabled: #808080;

$color-background-mouseover: #00a7dc;
$color-foreground-mouseover: white;

$color-background-mousedown: #00467F;
$color-foreground-mousedown: white;

.Tab
{
    background-color: $color-background-default;
    color:            $color-foreground-default;

    :hover
    {
        background-color: $color-background-mouseover;
        color:            $color-foreground-mouseover;
    }
    :active
    {
        background-color: $color-background-mousedown;
        color:            $color-foreground-mousedown;
        border-color:     $color-background-mousedown;
    }
}

In the CSS box of Sassmeister you should see, that there are whitespaces between ".Tab" and "hover" and "active" that look like this:

.Tab {
  background-color: white;
  color: black;
}
//WHITESPACE AFTER Tab
.Tab :hover {
  background-color: #00a7dc;
  color: white;
}
 //WHITESPACE AFTER Tab
.Tab :active {
  background-color: #00467F;
  color: white;
  border-color: #00467F;
}

Now when I remove the whitespaces between Tab and hover and active it looks like this:

.Tab {
  background-color: white;
  color: black;
}
//NO WHITESPACE AFTER Tab!
.Tab:hover {
  background-color: #00a7dc;
  color: white;
}
 // NO WHITESPACE AFTER Tab!
.Tab:active {
  background-color: #00467F;
  color: white;
  border-color: #00467F;
}

The second option without whitespaces gives me the correct UI result.

My question: How can I avoid these whitespaces in Angular 7?

seven-phases-max
  • 11,765
  • 1
  • 45
  • 57
Michael
  • 938
  • 1
  • 10
  • 34
  • Yes, this is a duplicate, but I could not find the right answer, because the other question said nothing about unwanted whitespaces. I am very new to SASS and Angular. – Michael Jun 03 '19 at 01:03

2 Answers2

4

The parent selector, &, is a special selector invented by Sass that’s used in nested selectors to refer to the outer selector. It makes it possible to re-use the outer selector in more complex ways, like adding a pseudo-class or adding a selector before the parent. (from SASS official documentation)

So when you write rules for pseudo-class (before, after, hover, active etc.), to refer to the outer selector (only one level higher), put the ampersand like this:

.link {
  color: blue;

  &:hover {
    color: green;
  }
}

So, your SCSS code can be rewritten as:

$color-background-default:  white;
$color-foreground-default:  black;

$color-background-disabled: #d3d3d3;
$color-foreground-disabled: #808080;

$color-background-mouseover: #00a7dc;
$color-foreground-mouseover: white;

$color-background-mousedown: #00467F;
$color-foreground-mousedown: white;

.Tab
{
    background-color: $color-background-default;
    color:            $color-foreground-default;

    &:hover
    {
        background-color: $color-background-mouseover;
        color:            $color-foreground-mouseover;
    }

    &:active
    {
        background-color: $color-background-mousedown;
        color:            $color-foreground-mousedown;
        border-color:     $color-background-mousedown;
    }
}
Sergey Sklyar
  • 1,902
  • 1
  • 15
  • 27
  • Thank you Sergey! I could not find the question/answer before, because the duplicate question did not say anything about whitespaces. You made my day! – Michael Jun 03 '19 at 00:58
2

You're looking for the sass ampersand.

.Tab {
  :hover {
     ...
  }
}

...should be:

.Tab {
  &:hover {
     ...
  }
}

& means: "current selector". You use &:hover to specify
#{currentSelector}:hover.

Without the ampersand, it results into #{currentSelector} :hover and that's the way you want it to work for constructs like

.a {
   .b {
     ...
   }
}

... which parses as .a .b {...}.

A more ample explanation here.


Note: the ampersand also allows specifying a prefix to current selector. For example:

.a {
  .b {
    prop: value;
    .c & {
       prop: otherValue;
    }
  }
}

will parse into:

.a .b { prop: value; }
.c .a .b { prop: otherValue; }
tao
  • 82,996
  • 16
  • 114
  • 150