I wanna be able to do something like so:
.myTransitionableElement {
transition: all .5s;
.subChild { transition: all 1s }
#include transitionKeyframes(
start: {
opacity: 0;
transform: tranlsate(50px);
.subChild {
transform: rotate(45deg);
}
},
end: {
opacity: 1;
transform: tranlsate(0);
.subChild {
transform: rotate(0);
}
}
)
}
#mixin transitionKeyframes($args) {
&.transitionStartKeyframe {
#include map_get($args, "start");
}
&.transitionEndKeyframe {
#include map_get($args, "end");
}
}
Which should at the end be equivalent to:
.myTransitionableElement {
transition: all .5s;
.subChild { transition: all 1s }
&.transitionStartKeyframe {
opacity: 0;
transform: tranlsate(50px);
.subChild {
transform: rotate(45deg);
}
}
&.transitionEndKeyframe {
opacity: 1;
transform: tranlsate(0);
.subChild {
transform: rotate(0);
}
}
}
The reason behind this is that I wanna find a way to not have to remember those classes names every time I use a JS abstraction that uses those classes.
You can't pass different content as arguments in SASS mixins.
Below is example of what you can achieve using SASS.
Can you specify what you want to achieve here?
#mixin rtl() {
&.ltr {
#content;
direction: ltr;
}
&.rtl {
#content;
direction: rtl;
}
}
.parent {
#include rtl {
display: flex;
}
}
You can try different approaches here. In this particular one I'm using map to hold the data for me. But if attributes and class names are fixed; you can even simplify it.
$map: (Start: (self: (opacity: '0', transform: 'tranlsate(50px)'), child: (transform: rotate(45deg))), End: (self: (opacity: '1', transform: 'tranlsate(0)'), child: (transform: rotate(0))));
$prefix: transition; $postfix: Keyframe;
#mixin transitionKeyframes($map) {
#each $key, $val in $map {
&.#{$prefix}#{$key}#{$postfix} {
#each $attr, $prop in map-get($val, self) {
#{$attr}: #{$prop};
}
.subChild {
#each $attr, $prop in map-get($val, child) {
#{$attr}: #{$prop};
}
}
}
}
}
.myTransitionableElement {
#include transitionKeyframes($map);
transition: all .5s;
.subChild { transition: all 1s }
}
Use mixins for a repetitive task. Modify the mixin or $frames if you have many variations. Breakdown opacity and transistion further to smaller mixins and invoke them conditionally.
$prefix: transition; $postfix: Keyframe;
$frames: 'Start', 'End';
$opcity-main: ('Start': 0, 'End': 1);
$translate-main: ('Start': 50, 'End': 0);
#mixin transitionKeyframes($frame) {
#each $key in $frame {
&.#{$prefix}#{$key}#{$postfix} {
$opacity: map-get($opcity-main, $key);
$translate: map-get($translate-main, $key);
opacity: $opacity;
transform: tranlsate($translate + px);
}
}
}
.myTransitionableElement {
#include transitionKeyframes($frames);
transition: all .5s;
.subChild { transition: all 1s }
}
I have an array called $ratings-list that I'm trying too loop through and if the $current-class contains .5 then to use a a segment of css otherwise use a different segment;
$ratings-list: 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5;
#each $current-class in $ratings-list {
$i: index($ratings-list, $current-class);
&[data-rating="#{$current-class}"] {
#if (index($current-class, .5)) {
.rating-stars__star:nth-child(-n+#{floor($current-class)}) .ratings-star {
height: floor($current-class);
}
} #else {
.rating-stars__star:nth-child(-n+#{$i}) .ratings-star {
height: 7px;
}
}
}
}
The above always returns the else height: 7px segment.
You could turn $current-class into a string and use str-index instead.
$ratings-list: 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5;
#each $current-class in $ratings-list {
$i: index($ratings-list, $current-class);
[data-rating="#{$current-class}"] {
#if (str-index(#{"" + $current-class}, '.5')) {
.rating-stars__star:nth-child(-n+#{floor($current-class)}) .ratings-star {
height: floor($current-class);
}
} #else {
.rating-stars__star:nth-child(-n+#{$i}) .ratings-star {
height: 7px;
}
}
}
}
Compiles to
[data-rating="1"] .rating-stars__star:nth-child(-n+1) .ratings-star {
height: 7px;
}
[data-rating="1.5"] .rating-stars__star:nth-child(-n+1) .ratings-star {
height: 1;
}
[data-rating="2"] .rating-stars__star:nth-child(-n+3) .ratings-star {
height: 7px;
}
[data-rating="2.5"] .rating-stars__star:nth-child(-n+2) .ratings-star {
height: 2;
}
[data-rating="3"] .rating-stars__star:nth-child(-n+5) .ratings-star {
height: 7px;
}
[data-rating="3.5"] .rating-stars__star:nth-child(-n+3) .ratings-star {
height: 3;
}
[data-rating="4"] .rating-stars__star:nth-child(-n+7) .ratings-star {
height: 7px;
}
[data-rating="4.5"] .rating-stars__star:nth-child(-n+4) .ratings-star {
height: 4;
}
[data-rating="5"] .rating-stars__star:nth-child(-n+9) .ratings-star {
height: 7px;
}
I have a loop that generates number from 0-5, but would like it to also generate up to 20, but in multiples of 5.
Desired results would be:
0, 1, 2, 3, 4, 5, 10, 15, 20
Is this possible in a single #for statement?
#for $i from 0 through 20 {
#if $i < 5 and $i > 0 {
.number-#{$i} {
height:(#{$i}px);
}
}
#if $i % 5 == 0 {
.number-#{$i} {
height:(#{$i}px);
}
}
}
The output would be
.number-0 {
height: 0px;
}
.number-1 {
height: 1px;
}
.number-2 {
height: 2px;
}
.number-3 {
height: 3px;
}
.number-4 {
height: 4px;
}
.number-5 {
height: 5px;
}
.number-10 {
height: 10px;
}
.number-15 {
height: 15px;
}
.number-20 {
height: 20px;
}
The for loop will go through 0 to 20. The I check 1-5 through the first if statement, the using modulus I I check divisible by 5.
How does one generate a list of classes for each key that has a single value inside a Scss/Sass map?
For example, from this Scss map (disregard nested naming conventions, this will be used for many maps of varying purposes):
(See Codepen: http://codepen.io/harlanlewis/pen/emWVrr (thanks cimmanon!))
$palette: (
brown: hsl(33,35,50),
blue: hsl(207,80,50),
green: (
0: hsl(157,65,65),
1: hsl(157,50,50),
alt: (
0: hsl(125,65,65),
),
),
red: (
0: hsl(0,60,50),
alt: (
0: hsl(0,100,50),
),
),
yellow: (
0: hsl(50,100,60),
1: hsl(50,100,100),
),
};
-
#mixin map-to-class($map, $selector: '', $property: '') {
$selector: if($selector == '' and &, &, $selector);
#each $key, $value in $map {
#if type-of($value) == map {
$selector: selector-append($selector, #{$key});
#include map-to-class($value, $selector, $property) {
#content;
}
} #else {
#at-root #{$selector}#{$key} {
#{$property}: $value;
};
};
};
};
#include map-to-class($palette, '.u-fg__', 'color')
...desired classes to generate:
.u-fg__brown { color: hsl(33,35,50) }
.u-fg__blue { color: hsl(207,80,50) }
.u-fg__green0 { color: hsl(157,65,65) }
.u-fg__green1 { color: hsl(157,50,50) }
.u-fg__greenalt0 { color: hsl(125,65,65) }
.u-fg__red0 { color: hsl(0,60,50) }
.u-fg__redalt0 { color: hsl(0,100,50) }
.u-fg__yellow0 { color: hsl(50,100,60) }
.u-fg__yellow1 { color: hsl(50,100,80) }
The actual (incorrect) generated classes are: (note greenredyellow instead of just yellow)
... (brown, blue, and green are fine) ...
.u-fg__green0 { color: hsl(157,65,65) }
.u-fg__green1 { color: hsl(157,50,50) }
.u-fg__greenalt0 { color: hsl(125,65,65) }
.u-fg__greenred0 { color: hsl(0,60,50) }
.u-fg__greenredalt0 { color: hsl(0,100,50) }
.u-fg__greenredyellow0 { color: hsl(50,100,60) }
.u-fg__greenredyellow1 { color: hsl(50,100,80) }
What you're looking for is a recursive mixin. Walk through the mapping. If the value is a mapping, call itself otherwise print out the property/value.
$palette: (
'brown': hsl( 33, 35, 50),
'blue': hsl(207, 80, 50),
'green': (
0: hsl(157, 65, 65),
1: hsl(157, 50, 50),
alt: (
0: hsl(125, 65, 65),
),
),
'red': (
0: hsl(0, 60, 50),
alt: (
0: hsl(0, 100, 50),
),
),
'yellow': (
0: hsl(50, 100, 60),
2: hsl(50, 100, 100),
),
);
#mixin map-to-class($map, $property, $sel, $divider: '') {
$sel: if($sel == '' and &, &, $sel);
#debug $sel;
#{$sel} {
#each $k, $v in $map {
#at-root #{$sel}#{$divider}#{$k} {
#if type-of($v) == map {
#include map-to-class($v, $property, '', $divider) {
#content;
}
} #else {
#{$property}: $v;
}
}
}
}
}
#include map-to-class($palette, color, '.u-fg__', '');
Output:
/* line 33, ../sass/test.scss */
.u-fg__brown {
color: #ac8453;
}
/* line 33, ../sass/test.scss */
.u-fg__blue {
color: #198ae6;
}
/* line 33, ../sass/test.scss */
.u-fg__green0 {
color: #6ce0b3;
}
/* line 33, ../sass/test.scss */
.u-fg__green1 {
color: #40bf8e;
}
/* line 33, ../sass/test.scss */
.u-fg__greenalt0 {
color: #6ce075;
}
/* line 33, ../sass/test.scss */
.u-fg__red0 {
color: #cc3333;
}
/* line 33, ../sass/test.scss */
.u-fg__redalt0 {
color: red;
}
/* line 33, ../sass/test.scss */
.u-fg__yellow0 {
color: #ffdd33;
}
/* line 33, ../sass/test.scss */
.u-fg__yellow2 {
color: white;
}
Note that I quoted your mapping key names. Sass will convert those to their hex code equivalents under certain compression types.
I'm using the following algorithm to create column classes in SASS:
$columns: 8;
$exclude-columns: 5 7;
#for $i from 1 through $columns {
#for $j from 1 through $i {
$width: (100% / $i) * $j;
#if $i != $j and index($exclude-columns, $i) {
.layout-unit-#{$j}of#{$i} {
width: $width;
}
}
}
}
It's working fine, however, the output has quite a bit of duplication:
.layout-unit-1of2 { width: 50%; }
.layout-unit-1of3 { width: 33.33333%; }
.layout-unit-2of3 { width: 66.66667%; }
.layout-unit-1of4 { width: 25%; }
.layout-unit-2of4 { width: 50%; }
.layout-unit-3of4 { width: 75%; }
.layout-unit-1of6 { width: 16.66667%; }
.layout-unit-2of6 { width: 33.33333%; }
.layout-unit-3of6 { width: 50%; }
.layout-unit-4of6 { width: 66.66667%; }
.layout-unit-5of6 { width: 83.33333%; }
.layout-unit-1of8 { width: 12.5%; }
.layout-unit-2of8 { width: 25%; }
.layout-unit-3of8 { width: 37.5%; }
.layout-unit-4of8 { width: 50%; }
.layout-unit-5of8 { width: 62.5%; }
.layout-unit-6of8 { width: 75%; }
.layout-unit-7of8 { width: 87.5%; }
Is there a way to get the output to look more like this:
.layout-unit-1of2,
.layout-unit-2of4,
.layout-unit-3of6,
.layout-unit-4of8 { width: 50%; }
.layout-unit-1of3,
.layout-unit-2of6 { width: 33.33333%; }
.layout-unit-2of3,
.layout-unit-4of6 { width: 66.66667%; }
.layout-unit-1of4,
.layout-unit-2of8 { width: 25%; }
.layout-unit-3of4,
.layout-unit-6of8 { width: 75%; }
.layout-unit-1of6 { width: 16.66667%; }
.layout-unit-5of6 { width: 83.33333%; }
.layout-unit-1of8 { width: 12.5%; }
.layout-unit-3of8 { width: 37.5%; }
.layout-unit-5of8 { width: 62.5%; }
.layout-unit-7of8 { width: 87.5%; }
Or is this a limitation of SASS?
It's not a limitation of Sass, but the algorithm.
Here is a solution that requires at least Sass 3.3 (see live demo on SassMeister):
Note: I fixed your code to support the exclusion of columns.
$columns: 8;
$exclude-columns: 5 7;
// A stack to store the different widths.
$width_stack: ();
#for $i from 1 through $columns {
#for $j from 1 through $i {
#if $i != $j and not index($exclude-columns, $i) {
$width: (100% / $i) * $j;
// Compute the number 66.66667% to a valid CSS selector: "66-66667".
$width_unitless: $width / 1% + unquote("");
$width_dot: str-index($width_unitless, '.');
#if $width_dot {
$width_unitless: str-slice($width_unitless, 0, $width_dot - 1) +
"-" +
str-slice($width_unitless, $width_dot + 1);
}
// Manage the stack of known widths to avoid repeats.
#if not index($width_stack, $width_unitless) {
$width_stack: append($width_stack, $width_unitless);
// Dynamic placeholder!
%mycols-#{$width_unitless} {
width: $width;
}
}
.layout-unit-#{$j}of#{$i} {
#extend %mycols-#{$width_unitless};
}
}
}
}