CSS/SCSS - value depends on selector - css

With an accordion each level having a incrementing margin as it goes deeper:
Level 1A
Level 2
Level 3
Level 4
Level 1B
...
CSS:
.level1 {
margin: 1em;
}
.level2 {
margin: 3em;
}
.level3 {
margin: 5em;
}
...
Is there CSS/SCSS syntax like:
.level[n] {
margin: (2n-1)em
}

In SASS/SCSS you can create for loops and generate the necessary amount of classes.
SASS:
#for $i from 1 through 4
.level#{$i}
margin: (2 * $i - 1) * 1em
SCSS:
#for $i from 1 through 4 {
.level#{$i} {
margin: (2 * $i - 1) * 1em ;
}
}
I'm pretty sure there is no pure CSS solution.

Related

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

How to evaluate variable inside the css pseudo class in SASS

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}) *

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

SASS: MIXIN for set heights

First time asking here.
I'm trying to make somekind of MIXIN in order to set heights for an element.
For example < span class="space h5" >< /span > in CSS this would be:
$size: 1px;
.space {
display: block;
}
.space.x5 {
height: $size * 5;
}
So my question, is it possible to create a mixin to multiply, add up or subtract amounts with classes?
For example
< span class=" space h5 x2 add4 ">< /span > ====> height: 14px
or:
< span class=" space h5 x4 subtract2 ">< /span > ====> height: 18px
Thanks a lot!
Regards.
#mixin height-special($default,$multiplier: 1,$extra: 0) {
height: ($default*$multiplier+$extra) + px;
}
So, height-special(5,2,4) will return 14
you can leave out the last 2 which will return the default value.
It's a nice solution but I was looking for something more like a loop:
.space {
display: block;
clear: both;
}
$space-base: 5px;
/*multipliers*/
#for $space-base from 1 through 100 {
.h5x#{$space-base} {
height: $space-base * 5px;
}
}
/*add*/
.h5x2.add-1 {
height: ($space-base * 2 + 1);
}
.h5x2.add-2 {
height: ($space-base * 2 + 2);
}
.h5x2.add-3 {
height: ($space-base * 2 + 3);
}
.h5x2.add-4 {
height: ($space-base * 2 + 4);
}
.h5x2.add-5 {
height: ($space-base * 2 + 5);
}
.h5x2.add-6 {
height: ($space-base * 2 + 6);
}
.h5x2.add-7 {
height: ($space-base * 2 + 7);
}
.h5x2.add-8 {
height: ($space-base * 2 + 8);
}
.h5x2.add-9 {
height: ($space-base * 2 + 9);
}
/*subtract*/
.h5x2.sub-1 {
height: ($space-base * 2 - 1);
}
I was trying to avoid all the combination by hand and do it with SASS.

How do I change the unit of multiple numbers in a Less mixin?

I am trying to create a mixin whereby I can change the unit from px to rem. For now, I have the following code:
#emSize : 16px;
#pxr : 1 / unit(#emSize, rem);
.padding(#padding) {padding: #padding * #pxr;}
.test {.padding(10px);}
This works fine if I only have one number in the mixin, but it does not work if I have multiple numbers. For instance, this does NOT work:
.test {.padding(10px 25px);}
What I cannot figure out is how to I could get this to work in Less.
Option 1
You can use the comma separated values to achieve the same with your minimal code:
#emSize : 16px;
#pxr : 1 / unit(#emSize, rem);
.padding(#verticalpad, #horizontalpad) {
padding: (#verticalpad * #pxr) (#horizontalpad * #pxr);
}
.test {
.padding(10px, 25px);
}
See it working
Option 2
Did you tried with two functions separated?
#emSize : 16px;
#pxr : 1 / unit(#emSize, rem);
.paddingver(#paddingver) {
padding-top: #paddingver * #pxr;
padding-bottom: #paddingver * #pxr;
}
.paddinghor(#paddinghor) {
padding-left: #paddinghor * #pxr;
padding-right: #paddinghor * #pxr;
}
.test {
.paddingver(10px);
.paddinghor(25px);
}
See it working

Resources