Angular: SCSS / SASS compiler produces unwanted whitespaces [duplicate] - css

This question already has answers here:
Sass Nesting for :hover does not work [duplicate]
(2 answers)
Closed 3 years ago.
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?

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;
}
}

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; }

Related

How to nest this scss so that it still functions as expected

I have a scss file that I need to orgnanize by nesting some of these properties, I've tried to nest them but the properties do not seem to work when I nest them. I was just wondering if there is a proper way to do it, thanks in advance!
This is how it is working at the moment:
input~.checked-icon {
color: $primary-color;
background-color: transparent;
&:hover {
background-color: transparent;
}
}
input:disabled~.checked-icon {
color: $disabled-color;
}
This is what i've tried:
input~.checked-icon {
color: $primary-color;
background-color: transparent;
&:hover {
background-color: transparent;
}
&:disabled {
color: $disabled-color;
}
}
Your current solution is creating a selector that looks like this:
input ~ .checked-icon:disabled {
color: $disabled-color;
}
where the :disabled is applied to the .checked-icon.
The additional :disabled rule needs to be applied to the input, so you would want to use:
input {
&~.checked-icon {
color: $primary-color;
background-color: transparent;
&:hover {
background-color: transparent;
}
}
&:disabled~.checked-icon {
color: $disabled-color;
}
}
Keep in mind there are lots of useful online tools for playing with Sass and viewing the compiled code. Like Sassmeister.

why variables in css is not working although I had read a lot about it?

I have variables in my css but it isn't recognized.I have tried setting variable like the code below but when I run it in chrome it doesn't work.
li {
border: 2px solid red;
}
:special {
background: yellow;
--col: blue;
}
.completed {
text-decoration: line-through lime;
color: var(--col);
}
but when I set to blue directly it works like that
li {
border: 2px solid red;
}
:special {
background: yellow;
--col: blue;
}
.completed {
text-decoration: line-through lime;
color: blue;
}
I don't understand what is the problem.
:special isn't a recognised selector which is most likely causing your problem here. People tend to add global custom CSS property declarations to the :root {} selector. Or simply scope them to the parent selector that you're using.
:root {
--col: blue;
}
.class-name {
color: var(--col);
}
:special is an invalid selector. Rules in invalid selectors are ignored as per the specification, so your variable is never defined.

Property for specific selector

1. Summary
I have list of selectors, to which properties should always apply.
For some selectors must be additionally added another properties.
I can't find, how I can do it without duplicates.
2. MCVE
2.1. Expected CSS
.KiraFirst,
.KiraSecond,
.KiraThird {
color: red;
}
.KiraSecond {
background-color: yellow;
}
In example, I use class .KiraSecond 2 times. Can I get expected behavior without this duplicate?
2.2. Stylus
Live demo on stylus-lang.com
.KiraFirst
.KiraSecond
.KiraThird
color red
.KiraSecond
background-color yellow
This is compiled to expected CSS, but I still use .KiraSecond 2 times.
I don't understand, how I can not use duplicate. For example, syntax as this not compile to expected CSS:
.KiraFirst
.KiraSecond
background-color yellow
.KiraThird
color red
Result:
.KiraFirst,
.KiraSecond {
background-color: #ff0;
}
.KiraThird {
color: #f00;
}
3. Not helped
Stylus official documentation include Selectors section
Stack Overflow Stylus questions
Stylus GitHub issues
Maybe you can use basic class for all elements? For example - .Kira and if you need to specify something for other elements you can add extra class .KiraSecond or use .Kira:nth-child(2)
in your example it can be something like this
.Kira {
color: red;
}
.KiraSecond {
background-color: yellow;
}
or
.Kira {
color: red;
}
.Kira:nth-child(2) {
background-color: yellow;
}
You (can't)? and you shouldn't.
Duplicating that selector in that case is not a bad practice.
you are not duplicating the same property/value for many classes
you can clearly override specific property
you can clearly modify/change behaviour for specific class
e.g:
.class1, .class2, .class3 {
color: red;
background: yellow;
border: 1px solid;
}
.class1:hover {
color: blue;
}
.class2 {
border: 2px dotted;
}
.class3 {
color: pink;
}
What would be a bad practice in that case (with no selector duplication)
.class1 {
color: blue;
background: yellow;
border: 1px solid;
}
.class2 {
color: red;
background: yellow;
border: 2px dotted;
}
.class3 {
color: pink;
background: yellow;
border: 1px solid;
}

How to use multiple ampersands for an anchor element?

scss
a {
text-decoration: none;
&:active {
color: $color-secondary;
}
&:visited {
color: $color-primary;
}
&:hover {
color: $color-accent;
}
}
css
a:active {
color: #E4E4E4;
}
a:visited {
color: #333;
}
a:hover {
color: #6DB48B;
}
The compiled css only takes the last property into consideration.
How do I use multiple ampersands for an anchor element?
The :active styles fail to show because they get overridden by the styles that appear lower down in your Sass. To fix this, reorder your Sass in this order:
:visited
:hover
:active

Why does SASS modify chained selectors of the same name when using extend?

Given the following HTML / SASS code:
<div class="a">hello</div>
%color {
color: blue;
}
.a {
color: red;
}
.a.a {
#extend %color;
}
I was expecting the resulting color to be blue (due to the more specific .a.a selector1) with output something like this:
.a.a {
color: blue;
}
.a {
color: red;
}
But actually, the resulting color is red, with SASS output:
.a {
color: blue;
}
.a {
color: red;
}
I find this quite counter-intuitive!
Why does SASS refactor my .a.a selector to .a?
Just in case you don't believe me, here's a codepen demo (click view compiled css to see the CSS output)
NOTE:
This 'refactoring' of the selector only occurs to the declarations within the extend.
So in the following SASS:
%color {
color: blue;
}
.a.a {
#extend %color;
position: relative;
}
The output is:
.a {
color: blue;
}
.a.a {
position: relative;
}
(Codepen demo)
1See the spec:
Note: Repeated occurrences of the same simple selector are allowed and
do increase specificity.
By the looks of it, the result depends on the parsing engine. If you use DartSass v1.6.2 (default on sassmeister.com), it outputs your expected result:
.a.a {
color: blue;
}
.a {
color: red;
}
Check on sassmeister.com (you can also switch parsing engines there).
LibSass v3.5.2 creates the result you complained about:
.a {
color: blue;
}
.a {
color: red;
}

Resources