How to evaluate variable inside the css pseudo class in SASS - css

I'm new to SASS. I want to get the css which evaluate the value inside the CSS class using for loop SASS. In my case, i want to get ul:nth-child(1) .e-classA instead of ul:nth-child(2) .e-classA. I'm getting error when used &ul:nth-child(#{$i} - 1)
$text-indent: 12px;
$width: 14px;
#for $i from 2 through 4 {
&ul:nth-child(#{$i} - 1) {
& .e-classA {
text-indent: $text-indent * #{$i};
&.e-classB {
text-indent: ($text-indent * #{$i}) + $width;
}
}
}
}
Actual output:
Error: Invalid CSS after "...m 2 through 4 {": expected "}", was "nth-child(#{$i}..."
on line 4 of stdin
>> #for $i from 2 through 4 {
--------------------------^
Expected output:
ul:nth-child(1) .e-classA {
text-indent: 24px;
}
ul:nth-child(1) .e-classA.e-classB {
text-indent: 38px;
}
ul:nth-child(2) .e-classA {
text-indent: 36px;
}
ul:nth-child(2) .e-classA.e-classB {
text-indent: 50px;
}
ul:nth-child(3) .e-classA {
text-indent: 48px;
}
ul:nth-child(3) .e-classA.e-classB {
text-indent: 62px;
}

If you want SASS to do some math, move the calculation inside #{...}. Second problem might be the & at the beginning of &ul:..., you don't need it there to get the result.
I fixed you code:
$text-indent: 12px;
$width: 14px;
#for $i from 2 through 4 {
ul:nth-child(#{$i - 1}) {
& .e-classA {
text-indent: #{$text-indent * $i};
&.e-classB {
text-indent: #{($text-indent * $i) + $width};
}
}
}
}
And tested in sassmeister and it works.

Resolved myself by the below modification.
*&ul:nth-child(#{$i - 1}) *

Related

Different Classes separated with comma in SCSS using #for

I want to render this css below using SCSS:
.aem-Grid.aem-Grid--1>.aem-GridColumn.aem-GridColumn--offset--default--1,
.aem-Grid.aem-Grid--default--1>.aem-GridColumn.aem-GridColumn--offset--default--1,
.aem-Grid.aem-Grid--2>.aem-GridColumn.aem-GridColumn--offset--default--2,
...
..
. {
margin-left: $pc-100;
}
Using this #for below:
#for $i from 1 through 12 {
.aem-Grid.aem-Grid--#{$i}>.aem-GridColumn.aem-GridColumn--offset--default--#{$i} {
margin-left: $pc-100;
}
}
But this code renders all separated:
.aem-Grid.aem-Grid--1 > .aem-GridColumn.aem-GridColumn--offset--default--1 {
margin-left: 100%;
}
.aem-Grid.aem-Grid--2 > .aem-GridColumn.aem-GridColumn--offset--default--2 {
margin-left: 100%;
}
...
..
.
I've tried to use "&, &aem-Grid..." but render the same css. Could someone give me a hand?
You may take a look at #extend. Documentation https://sass-lang.com/documentation/at-rules/extend
Input
$pc: 1000;
%margin-styles {
margin-left: $pc - 100;
}
#for $i from 1 through 12 {
.aem-Grid.aem-Grid--#{$i}>.aem-GridColumn.aem-GridColumn--offset--default--#{$i} {
#extend %margin-styles;
}
}
Output
.aem-Grid.aem-Grid--12 > .aem-GridColumn.aem-GridColumn--offset--default--12,
.aem-Grid.aem-Grid--11 > .aem-GridColumn.aem-GridColumn--offset--default--11,
.aem-Grid.aem-Grid--10 > .aem-GridColumn.aem-GridColumn--offset--default--10,
.aem-Grid.aem-Grid--9 > .aem-GridColumn.aem-GridColumn--offset--default--9,
.aem-Grid.aem-Grid--8 > .aem-GridColumn.aem-GridColumn--offset--default--8,
.aem-Grid.aem-Grid--7 > .aem-GridColumn.aem-GridColumn--offset--default--7,
.aem-Grid.aem-Grid--6 > .aem-GridColumn.aem-GridColumn--offset--default--6,
.aem-Grid.aem-Grid--5 > .aem-GridColumn.aem-GridColumn--offset--default--5,
.aem-Grid.aem-Grid--4 > .aem-GridColumn.aem-GridColumn--offset--default--4,
.aem-Grid.aem-Grid--3 > .aem-GridColumn.aem-GridColumn--offset--default--3,
.aem-Grid.aem-Grid--2 > .aem-GridColumn.aem-GridColumn--offset--default--2,
.aem-Grid.aem-Grid--1 > .aem-GridColumn.aem-GridColumn--offset--default--1 {
margin-left: 900;
}

Syntax for if/else condition in SCSS mixins

I created a SASS #mixin which contains #if conditions to assign styling to elements based on their z-index property to create some sort of elevation.
However what ever I am trying it will not work out.
I'm pretty sure I am doing something just slightly wrong that affects everything else.
I'd appreciate your feedback. Thanks in advance!
$background: #121212;
$surface: #1f1f1f;
$surface-shade_1: #282828;
$surface-shade_2: #303030;
%surface {
background-color: $surface;
}
%surface-shade_1 {
background-color: $surface-shade_1;
}
%surface-shade_2 {
background-color: $surface-shade_2;
}
#mixin elevation($elevationValue) {
#if $elevationValue>0 {
#extend %surface;
}
#else if $elevationValue>4 or $elevationValue=4 {
#extend %surface-shade_1;
}
#else if $elevationValue>8 or $elevationValue=8 {
#extend %surface-shade_2;
}
z-index: $elevationValue * 50;
}
nav {
#mixin elevation(4);
}
If you want to use #mixin inside the CSS files you can use like #include mixin-name and also use directly $elevationValue >= 4 instead of $elevationValue>4 or $elevationValue=4 it becomes much cleaner.
$background: #121212;
$surface: #1f1f1f;
$surface-shade_1: #282828;
$surface-shade_2: #303030;
%surface {
background-color: $surface;
}
%surface-shade_1 {
background-color: $surface-shade_1;
}
%surface-shade_2 {
background-color: $surface-shade_2;
}
#mixin elevation($elevationValue) {
#if $elevationValue > 0 {
#extend %surface;
}
#else if $elevationValue >= 4 {
#extend %surface-shade_1;
}
#else if $elevationValue >= 8 {
#extend %surface-shade_2;
}
z-index: $elevationValue * 50;
}
nav {
#include elevation(4);
}

How can I use a loop in LESS to create specific class names for typography?

I want to generate 9 typography classes, each with the following:
font-size: 2rem;
line-height: 1rem;
I'll be using standard typographic multipliers for font sizes and line-height. Instead of hard-coding all of these CSS classes, I was wondering if there was a more elegant way of generating them in a loop using LESS.
I found the following from another thread:
#iterations: 5;
.span-loop (#i) when (#i > 0) {
.span-#{i} {
width: ~"#{i}%";
}
.span-loop(#i - 1);
}
.span-loop (#iterations);
Which generates:
.span-5 {
width: 5%;
}
.span-4 {
width: 4%;
}
.span-3 {
width: 3%;
}
.span-2 {
width: 2%;
}
.span-1 {
width: 1%;
}
This is pretty close, but I'd love for my class names to more "named". How can I use a loop to generate classes for:
.small { }
.caption { }
.body { }
.subheader { }
.title { }
.headline { }
etc...
I'm also not tied to LESS, so if there's a better CSS preprocessor language, then I'm happy to use that instead :)
Thank you!
An example from documentation for further modification;)
for more complicated code, it is better to use scss than less
.for(#list, #code) {
& {
.loop(#i: 1) when (#i =< length(#list)) {
#value: extract(#list, #i);
#code();
.loop(#i + 1);
}
.loop();
}
}
#elements: small, caption, body, subheader, title, headline;
.for(#elements, {
#remfont: #i+1;
#remline: ((#i+1) * 1.5 / 3);
.#{value} {
font-size: ~"#{remfont}rem";
line-height: ~"#{remline}rem";
}
});

postcss - css variable as argument inside postcss-mixins

I have a mixin made with postcss-mixins and I want to use a css variable as argument, but it isn't working.
:root {
--padd: 2rem;
}
#define-mixin position $place, $val {
#if $place == end { right: $(val); }
#if $place == start { left: $(val); }
}
And then I call it:
.foo1 {
#mixin position end, 2rem; /* it works -> right: 2rem; */
}
.foo2 {
#mixin position end, var(--padd); /* doesn't work -> right: var(--padd); - it should output 2rem */
}
How can I manage to be able using css variables with postcss-mixins?

Dynamic classes and values

I have helper classes like the following for all directions (both margin and padding):
.h-space-top-10 {margin-top: 10px;}
.h-space-top-20 {margin-top: 20px;}
.h-space-top-30 {margin-top: 30px;}
Is there anyway to create those with Sass to have dynamic values (e.g. up to 10x the base value 10px) or would one have to write them out manually?
#for $i from 1 through 3 {.h-space-top-#{$i * 10} {margin-top:#{$i * 10}px}}
$properties: (margin padding);
$positions: (top right bottom left);
$range: 10;
#each $property in $properties {
#each $item in $positions {
#for $ii from 1 through $range {
.h-#{$property}-#{$item}-#{$ii * 10} { #{$property}-#{$item}: #{$ii * 10}px; }
}
}
}
You may define two variables: number of repetitions and number of px to jump in each repetition. Something like this:
$numRepetitions: 3;
$pxJump: 10;
#for $i from 1 through $numRepetitions {
.h-space-top-#{$i * $pxJump} {
margin-top:#{$i * $pxJump}px
}
}
The output for that case would be the code you need:
.h-space-top-10 {
margin-top: 10px;
}
.h-space-top-20 {
margin-top: 20px;
}
.h-space-top-30 {
margin-top: 30px;
}
However, if you need for example to iterate 4 times and summing 5px in each jump you just need to change the value of the variables, like this:
$numRepetitions: 4; //4 instead of 3 repetitions
$pxJump: 5; //5px instead of 10px
#for $i from 1 through $numRepetitions {
.h-space-top-#{$i * $pxJump} {
margin-top:#{$i * $pxJump}px
}
}
In that case you'll get this code:
.h-space-top-5 {
margin-top: 5px;
}
.h-space-top-10 {
margin-top: 10px;
}
.h-space-top-15 {
margin-top: 15px;
}
.h-space-top-20 {
margin-top: 20px;
}

Resources