Dynamic classes and values - css

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

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

CSS/SCSS - value depends on selector

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.

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?

Using SASS's #for for multiple selectors and 1 body [duplicate]

I'm working with the SCSS syntax of SASS to create a dynamic grid system but I've hit a snag.
I'm trying to make the grid system completely dynamic like this:
$columns: 12;
then I create the columns like this:
#mixin col-x {
#for $i from 1 through $columns {
.col-#{$i} { width: $column-size * $i; }
}
}
Which outputs:
.col-1 {
width: 4.16667%;
}
.col-2 {
width: 8.33333%;
}
etc...
This works well but what I want to do next is dynamically generate a long list of column classes separated by commas based on the number of $columns chosen - e.g I want it to look like this:
.col-1,
.col-2,
.col-3,
.col-4,
etc... {
float: left;
}
I've tired this:
#mixin col-x-list {
#for $i from 1 through $columns - 1 {
.col-#{$i}-m { float: left; }
}
}
but the output is this:
.col-1 {
float: left;
}
.col-2 {
float: left;
}
etc...
I'm a little stuck on the logic here as well as the SCSS syntax required to create something like this.
Does anyone have any ideas?
I think you may want to take a look at #extend. If you set that up something like:
$columns: 12;
%float-styles {
float: left;
}
#mixin col-x-list {
#for $i from 1 through $columns {
.col-#{$i}-m { #extend %float-styles; }
}
}
#include col-x-list;
It should render in your css file as:
.col-1-m, .col-2-m, .col-3-m, .col-4-m, .col-5-m, .col-6-m, .col-7-m, .col-8-m, .col-9-m, .col-10-m, .col-11-m, .col-12-m {
float: left;
}
#extend in the docs.
There's also a way to do what your question is specifically asking for: generate (and use) a list of classes with commas separating them. D.Alexander's response totally works in your situation, but I'm posting this alternative in case there's another use case for someone looking at this question.
Here's a Pen demonstrating: http://codepen.io/davidtheclark/pen/cvrxq
Basically, you can use Sass functions to achieve what you want. Specifically, I'm using append to add classes to my list, separated by commas, and unquote to avoid compilation conflicts with the period in the classnames.
So my mixin ends up looking like this:
#mixin col-x {
$col-list: null;
#for $i from 1 through $columns {
.col-#{$i} {
width: $column-size * $i;
}
$col-list: append($col-list, unquote(".col-#{$i}"), comma);
}
#{$col-list} {
float: left;
}
}
thnx to #davidtheclark here is a more generic version:
#mixin attr-x($attr, $attr-count: 10, $attr-steps: 10, $unit: '%') {
$attr-list: null;
#for $i from 1 through $attr-count {
$attr-value: $attr-steps * $i;
.#{$attr}#{$attr-value} {
#{$attr}: #{$attr-value}#{$unit};
}
$attr-list: append($attr-list, unquote(".#{$attr}-#{$attr-value}"), comma);
}
#{$attr-list} {
//append style to all classes
}
}
Use it like this:
#include attr-x('margin-left', 6, 5, 'px');
//or
#include attr-x('width');
The result looks like this:
.margin-left5 {
margin-left: 5px; }
.margin-left10 {
margin-left: 10px; }
...
.margin-left30 {
margin-left: 30px; }
.width10 {
width: 10%; }
.width20 {
width: 20%; }
...
.width100 {
width: 100%; }

Resources