How to increment up between 0 and 1 with scss - sass

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.

Related

Using sass #function inside #for

I have some sass function to create same margin, and it is inside loop like this
$short-margins: ( top: 'mt', left: 'ml', bottom: 'mb', right: 'mr' );
#for $i from 0 through 200 {
#each $position, $prefix in $short-margins{
.#{$prefix}-#{$i} {
margin-#{$position}: #{$i}px;
}
}
}
This will create margin classes like this mr-0 and so on until mr-200, the problem is in line
margin-#{$position}: #{$i}px;
There I create px in loop, but i need that to be in rem? I ahve some function like this
$base-font-size: 14px;
// Remove units from the given value.
#function strip-unit($number) {
#if type-of($number) == 'number' and not unitless($number) {
#return $number / ($number * 0 + 1);
}
#return $number;
}
// convert only single px value to rem
#function single-px-to-rem($value) {
$unitless-root-font-size: strip-unit($base-font-size);
#return $value / $unitless-root-font-size * 1rem;
}
But when i want to use function inside loop like this
#for $i from 0 through 200 {
#each $position, $prefix in $short-margins{
.#{$prefix}-#{$i} {
margin-#{$position}: single-px-to-rem(#{$i});
}
}
}
It does not compile throw me error, does any body knows how ti use sass #function inside #for?
You are doing it right, but you need to send the $i value without interpolation:
#for $i from 0 through 200 {
#each $position, $prefix in $short-margins{
.#{$prefix}-#{$i} {
margin-#{$position}: single-px-to-rem($i);
}
}
}

scss providing css classes with . inside

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?

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.

Trying to create a Sass mixin that writes a long list of semantic icon names appending a uniquely iterated number

Trying to create a Sass mixin that writes a long list of semantic icon names appending a uniquely iterated number.
Chunk of Sass
$icon-name: pencil trash calendar;
$icon-num: length($icon-name);
#for $i from 1 through $icon-num {
$class-slug: test-icon !default;
.#{$class-slug}-#{$icon-name}-#{$icon-num} {
content: $i;
}
}
RESULT:::::::::::::::::
.test-icon-pencil trash calendar-3 {
content: 1;
}
.test-icon-pencil trash calendar-3 {
content: 2;
}
.test-icon-pencil trash calendar-3 {
content: 3;
}
Figured it out - $collection is like a Sass array:
$collection: (pencil, trash, calendar);
$icon-num: length($collection);
$class-slug: test-icon !default;
#for $i from 0 to $icon-num {
$this-name: nth($collection, $i+1);
.#{$class-slug}-#{$this-name} {
content: $i;
}
}
Output renders:
.test-icon-pencil {
content: 0;
}
.test-icon-trash {
content: 1;
}
.test-icon-calendar {
content: 2;
}

Resources