Updating a SASS variable within an extended class - sass

Is there a way to update a SASS variable within an extended class? For example I have this currently:
.menu-highlight-1 {
$child: 1;
a {
&:nth-child(#{$child}) {
color: red !important;
}
}
}
And I want to update the $child variable to the next element, so in my attempt I've extended the .menu-highlight-1 class and then made a change to the $child variable. However all this does is highlight the same item from the extended class.
.menu-highlight-2 {
#extend .menu-highlight-1;
$child: 2;
}
Is this possible somehow?

The solution for this problem using a SASS mixin. Thanks to #cimmanon and this thread: Updating variables created by lighten/darken functions by modifying the original base color afterwards
#mixin _menuHighlight($child) {
a {
&:nth-child(#{$child}) {
color: red !important;
}
}
}
.menu-highlight-1 {
#include _menuHighlight(1);
}
.menu-highlight-2 {
#include _menuHighlight(2);
}

Related

Can I call SCSS functions programmatically listed in a map?

I'm creating my own utility class library similar to Tailwind CSS. I'd like to loop through a map of functions and apply those functions to every item in another map.
I'm looping through the colors, and then I'd like to loop through the transparency functions to programmatically create each class.
Here's what works:
#each $color-name, $color-value in $color-map {
.text-almost-#{$color-name} {
color: almost($color-value);
}
.text-mostly-#{$color-name} {
color: mostly($color-value);
}
.text-semi-#{$color-name} {
color: semi($color-value);
}
.text-kinda-#{$color-name} {
color: kinda($color-value);
}
.text-barely-#{$color-name} {
color: barely($color-value);
}
.text-transparent-#{$color-name} {
color: transparent($color-value);
}
}
But I'd like to consolidate it to this, because this same process is being run 10+ times throughout the file:
#each $color-name, $color-value in $color-map {
#each $opacity-name in $opacity-function-map {
.text-#{$opacity-name}-#{$color-name} {
color: $opacity-name($color-value);
}
}
}
But it's not working. $opacity-name($color-value) should be executing the transparency function on the color value. It's just outputting plain text.
So how do I programmatically run a list of functions from a map without listing out each function by name?

What does this sass statement mean?

I'm new to sass, could you please explain what the following statement mean?
[class*='icon--']::before {
#mixin icon;
}
Doe's it mean; add to ::before pseudo of all elements with a class, which begins with icon-- the icon mixin?
The above code is then used like this:
[class*='icon--']::before {
#mixin icon;
}
.icon--bag::before {
content: '\e602';
}
.icon--book::before {
content: '\e618';
}
Does it mean that the above code will be converted to this?
.icon--bag::before {
#mixin icon;
content: '\e602';
}
.icon--book::before {
#mixin icon;
content: '\e618';
}
It selects every class that contains the icon-- string and adds the icon mixin to its before pseudo element .
So lets say that mixin icon looks like
#mixin icon {
display: inline-block;
}
Then icon--bag would be
.icon--bag::before {
display: inline-block; /* from the mixin */
content: '\e602';
}

Is it possible to pass in variables such that it adds to the actual scss variables?

I have a scss code like below
.hello-station {
&-hello123 {
.site-logo__image {
#extend .logos--hello-123;
margin: 27px 0;
}
}
}
Now you can see that the word "hello" is repeated throughout... So is the number.
I will like to create a mixin or function such that the word and the number can be passed along as variables. Is that possible?
Pretty simple actually, Sass/SCSS offers a concatenation syntax:
$word: 'hello';
$number: 123;
.#{$word}-station {
&-#{$word}#{$number} {
.site-logo__image {
#extend .logos--#{$word}-#{$number};
margin: 27px 0;
}
}
}

How do I reference the parent selector at the end? [duplicate]

This question already has an answer here:
Append the parent selector to the end with Sass
(1 answer)
Closed 7 years ago.
How can I turn this:
.btn-primary {
.open .dropdown-toggle.btn-primary { ... }
}
into
.btn-primary {
.open .dropdown-toggle& { ... }
}
I keep getting invalid selector after .dropdown-toggle
If you read the complete error, it should say this:
"&" may only be used at the beginning of a compound selector.
However, .dropdown-toggle.btn-primary is the same as .btn-primary.dropdown-toggle. So place the parent selector at the beginning:
.btn-primary {
.open &.dropdown-toggle { color: blue; }
}
As of Sass 3.4, you can do that like this:
.btn-primary {
.open .dropdown-toggle#{&} { color: blue; }
}
No offense, but I'm not sure you understand what is & used for.. Just in case I'm right here is the explanation:
Sometimes it’s useful to use a nested rule’s parent selector in other ways than the default.
For instance, you might want to have special styles for when that selector is hovered over or
for when the body element has a certain class. In these cases, you can explicitly specify where the parent selector should be inserted using the & character.
Example:
p{
background: red;
&:hover{
background: blue;
}
&:active {
background: blue;
}
}
Which will be converted to this:
p {
background:red;
}
p:hover {
background:red;
}
p:active {
background:red;
}

Sass/Compass Getting variable name from variable

I'm trying to make a mixin that will let me create adapted blocks of code depending on what variable name you up in.
$foo: #00A9EC;
#mixin menu-color($color) {
.color-#{$color} a.level2,
.color-#{$color} a.level2:visited {
color: $color;
&:hover {
color: adjust-lightness($color, 10); }
&:active {
color: adjust-lightness($color, -10); } } }
#include menu-color($foo);
outputs:
.color-foo a.level2,
.color-foo a.level2:visited {
color: #00A9EC; }
.color-foo a.level2:hover,
.color-foo a.level2:visited:hover {
color: #20C0FF; }
.color-foo a.level2:active,
.color-foo a.level2:visited:active {
color: #0084B9; }
In sass you can do this using map, you just pass the variable name instead of the variable itself:
$colors: (
-black: #000,
-blue: #088DC6
);
#mixin generateBgColor($colorName) {
.bg-color#{$colorName} {
background-color: map-get($colors, $colorName);
}
}
#include generateBgColor("-blue");
This will generate class:
.bg-color-blue {
background-color: #088DC6;
}
You achieve this also in less with standard variables, just by using curly brackets and double at character:
#blue: #088DC6;
.generate-bg-color(#color) {
.bg-color-#{color} {
background-color: ##color;
}
}
.generate-bg-color(~"blue");
You should not name CSS classes after specific colors. You would regret that. Just think, if you want to make the color red later on, you would need to go back over all your html and change the classes.
The reason we have CSS is so that you don't have to embed style information in the markup.
Use a semantic class the describes the data, not how it is displayed:
$foo: #00A9EC;
#mixin menu-color($name, $color) {
.custom-#{$name} a.level2,
.custom-#{$name} a.level2:visited {
color: $color;
&:hover {
color: adjust-lightness($color, 10); }
&:active {
color: adjust-lightness($color, -10); } } }
#include menu-color(profile, $foo);
And then in your HTML <div class="custom-profile">.
That way, two years from now when you want to make it black, and underlined (or whatever), you don't have to dig through your html and add a new '.underlined-and-black-color` class to all of those elements. You just change your SCSS in one place.

Resources