scss providing css classes with . inside - for-loop

I have a for loop in scss and I would like to output something like this:
.font-1.0em {font-size:1.0em}
.font-1.1em {font-size:1.1em}
.font-1.2em {font-size:1.2em} ....
I wrote the scss as this
#for $i from 1 through 50 {
$val: $i + em;
$val2: $i / 10 + em;
&.font-#{$val} {
font-size: #{$val2} ;
}
}
which outputs
.font-10em {font-size:1.0em}
.font-11em {font-size:1.1em}
.font-12em {font-size:1.2em} ....
Is there anyway to fix this?

The thing you are trying to achive should be fairly easily solved, by using, same formula you have in $val2 in your $val
#for $i from 1 through 50 {
$val: $i / 10 + em;
$val2: $i / 10 + em;
&.font-#{$val} {
font-size: #{$val2} ;
}
}
compiles to
.font-0.1em {
font-size: 0.1em;
}
.font-0.2em {
font-size: 0.2em;
}
Or am I missing something?

Related

How to increment up between 0 and 1 with scss

In regards to SCSS, the following generates 2 classes for me between 0 and 1
#for $i from 0 through 1 {
.op-#{1 * $i} {
opacity: #{1 * $i};
}
}
which results in
.op-0 {
opacity: 0;
}
.op-1 {
opacity: 0.1;
}
but how can I get
.op-0 {
opacity:0;
}
.op-01 {
opacity:0.1;
}
.op-02 {
opacity:0.2;
}
//...etc...
.op-1 {
opacity:1.0;
}
I tried the following...
#for $i from 0 through 1 {
.op-#{0.10 * $i} { //I know this part is wrong - not sure how to do this correctly...
opacity: #{.10 * $i};
}
}
but it throws an error. Thanks for any tips!
If you do not want specific classname requirements then you can try below solutions, it will be just that your compiled css classnames will starts from .opacity1 to .opacity2.
All you need is loop thought 10 times.
#for $i from 1 through 10 { //means start from i=1 to till i=10, generate below css
.op-#{1 * $i} {
opacity: #{$i/10};
}
}
In sass for loop valid number after from is starting value of loop and whatever valid number we write after through is ending point.
#for $i from 1 through 10, this statement means start from 1 till 10.
opacity: #{$i/10};, just logic for generating expected opacity value.

Mixin (PXTOEM) provides error in CSS output

I use Drupal FortyTwo theme. The theme provides a mixin named PXTOEM:
// PXTOEM
// Calculate percentage with font-size as context
#function pxtoem($pixels...) {
$result: '';
#each $item in $pixels {
$result: $result + ($item + 0) / $default-font-size + em + ' ';
}
#return #{$result};
}
In my scss file I use it like:
.header-menus {
padding: pxtoem(0, $grid-gutter-width);
}
But after compiling it doesn't get the proper output?
padding: 0/pxem 0.75/pxem; (see screenshot)[![Screenshot][2]][2]
Instead of + 0 you should add pixels: + 0px. And instead of + em use + 0em.
Sassmeister demo.
If you can not modify source code of the theme, create your own function.
$default-font-size: 16px;
// PXTOEM
// Calculate percentage with font-size as context
#function pxtoem($pixels...) {
$result: '';
#each $item in $pixels {
$result: $result + ((($item + 0px) / $default-font-size) + 0em) + ' ';
}
#return #{$result};
}
.header-menus {
padding: pxtoem(0, 30, 30px);
}
Css output:
.header-menus {
padding: 0em 1.875em 1.875em ;
}

Why doesn't SASS resolve the calculation?

Why doesn't SASS resolve the calculation?
$animation-speed-half-life: 1s;
#for $i from 0 through 31 {
&:nth-child(#{$i}) {
transition-delay: #{$animation-speed-half-life - $animation-speed-half-life / $i};
}
}
Instead it outputs transition-delay: 1s - 1s/1;
I'm not sure why Sass won't calculate that but you don't actually need to interpolate the value of transition-delay, as there's no CSS going on around it.
This would be my implementation of your code:
#mixin incremental-transition-delay($child-count, $half-life: 1s) {
#for $i from 1 through $child-count {
&:nth-child(#{$i}) {
transition-delay: $half-life - $half-life / $i;
}
}
}
.thing {
#include incremental-transition-delay(32, 1s);
}
Did you already debug it?
I tested your code at Sassmeister (SASS v3.4.21), and it shows me a reference error:
Base-level rules cannot contain the parent-selector-referencing
character '&'.
DEBUG
$animation-speed-half-life: 1s;
$i: 1;
$test: #{$animation-speed-half-life - $animation-speed-half-life / $i};
#error $test; // this will render '0s' as expected
.parentElement { // comment this to show the reference error
#for $i from 0 through 31 {
&:nth-child(#{$i}) {
transition-delay: #{$animation-speed-half-life - $animation-speed-half-life / $i};
}
}
}
Sassmeister Fiddle
Not sure, if that's your complete code or just a snippet but it warns me the error I quoted above. It looks for a parent element which doesn't exist. Probably, that's why in your version it won't calculate. The .parentElement is just a dummy to provide you the working way.
POSSIBLE FIX
Add a #if-condition that checks if a parent element exists:
#if & { ... }
So basically wrap the condition around the loop:
#if & {
#for $i from 0 through 31 {
&:nth-child(#{$i}) {
transition-delay: #{$animation-speed-half-life - $animation-speed-half-life / $i};
}
}
}
Sassmeister Fiddle
The if & { .. statement is optional. Just wanted to show you how to bug out the error. I am not sure if your SASS version still interpolates the calculation during an error or not.
My own personal way would be using a placeholder without the if & statement because a placeholder functions as a parent element and no error will occur. Even if the element doesn't exist but that's what placeholders are for:
%test {
#for $i from 0 through 31 {
&:nth-child(#{$i}) {
transition-delay: #{$animation-speed-half-life - $animation-speed-half-life / $i};
}
}
}
parent {
#extend %test;
}
Sassmeister Fiddle
A Mixin would work also but your loop doesn't need any parameter to function so a placeholder should do it.

sass #for within #each, where #for is using key, value pair of #each

I was not able to find the answer to my question: WTF - why?!
Variables
$breakpointNames: (xs, sm, md, lg, xl);
$breakpointSizes: (480px, 667px, 845px, 1024px, 1280px);
$breakpoints: createMapOutOfLists($breakpointNames, $breakpointSizes);
$masonryLayoutColumnsCount: (2, 2, 3, 4, 4);
$masonryLayoutColumns: createMapOutOfLists($breakpointNames,
$masonryLayoutColumnsCount);
Mixin
#mixin media($min, $max: false) {
#if $max == false {
#if $min == xs {
#media (min-width: 0px) {
#content;
}
}
#media (min-width: #{map-get($breakpoints,$min)}) {
#content;
}
} #else if $min == 0 {
#media (max-width: (#{map-get($breakpoints,$max)} - 1)) {
#content;
}
} #else {
#media (min-width: #{map-get($breakpoints,$min)}) and (max-width: (#{map-get($breakpoints,$max)} - 1)) {
#content;
}
}
}
I wrote this:
#each $breakpoint, $column-count in $masonryLayoutColumns {
#include media($breakpoint) {
.masonry-tile {
width: 100% / $column-count;
}
}
#for $i from 1 through $column-count {
#include media($breakpoint) {
.masonry-tile:nth-child(#{$i}) {
-webkit-order: $i;
order: $i;
}
}
}
}
That threw following Error:
Error in plugin 'sass'
Message:
../../../app/Resources/assets/sass/functions/_map_generators.scss
Error: 2 is not an integer.
on line 4 of
../../../app/Resources/assets/sass/functions/_map_generators.scss
>> merge($map, (#{nth($listOfKeys, $index)}: #{nth($listOfValues, $index)}));
------------------------------------------^
That the error is at a wrong place or maybe entirely wrong, is another issue and currently irrelevant - to me - right now.
After some time of searching without results and trying to fix it on my own, I got it to work with the following:
#for $index from 1 through length($masonryLayoutColumns) {
$breakpoint: nth($breakpointSizes, $index);
$column-count: nth($masonryLayoutColumnsCount, $index);
#include media($breakpoint) {
.masonry-tile {
width: 100% / $column-count;
}
}
#for $i from 1 through $column-count {
#include media($breakpoint) {
.masonry-tile:nth-child(#{$i}) {
-webkit-order: $i;
order: $i;
}
}
}
}
Okay, that works, but I don't like it.
I prefer the first version.
Is there a good reason why the first version is not working? Or is it a bug?
Thanks in advance!
The only reason your code didn't work is because you must be passing a string in the map that you are creating.
$column-count should be an integer, in order to do your width manipulation (width: 100% / $column-count;)
I have attached a sample pen, with integer data, which will resolve your issue.
$masonryLayoutColumns: (
'760px': 8,
'990px': 12,
'1024px': 16
);
#each $breakpoint, $column-count in $masonryLayoutColumns {
#media(min-width: $breakpoint) {
.masonry-tile {
width: 100% / $column-count;
}
}
#for $i from 1 through $column-count {
#media(min-width: $breakpoint) {
.masonry-tile:nth-child(#{$i}) {
-webkit-order: $i;
order: $i;
}
}
}
}
https://codepen.io/anon/pen/LLBPaP
Note: I don't have your mixin's so I am just writing a generic media query.

How do I combine a range of sass classes that are created in a loop

I am using SASS to construct a range of classes from variables passed into a mixin.
#mixin classes($key, $num) {
#for $i from 1 through $num {
[class*=#{$key}-#{$i}] {
#content
}
}
}
#include classes(grid, 8) {
width:100px;
}
It currently makes the classes like I want, but all as 8 separate classes (which are identical in #contents. Is there a way to merge them all together so I get:
[class*=grid-1],
[class*=grid-2],
....
[class*=grid-8],
{
width:100px;
}
I'm not sure if it's even possible to do this? Any pointers would be greatly appreciated.
Thanks,
Carl
I found the answer eventually
$classes: ();
#for $i from 1 through $cols {
$classes: join($classes, unquote("#{$prefix}#{$i} "), comma);
}
#{$classes} {
float: left;
margin-right: $gutterPercent;
width: $columnWidth;
}

Resources