I have the below sass. In it I am have several charx classes, where x is between 1...7. is it possible to define them in a more concise way instead of defining each one of them individually ?
$first-color: #666666;
$second-color: #0066CC;
#mixin letter($color){
color: $color;
}
.char1{
#include letter($first-color);
}
.char2{
#include letter($second-color);
}
.char3{
#include letter($first-color);
}
.char4{
#include letter($second-color);
}
.char5{
#include letter($first-color);
}
.char6{
#include letter($second-color);
}
.char7{
#include letter($first-color);
}
You could possibly achieve the same effect with plain CSS:
$first-color: red;
$second-color: salmon;
span:nth-of-type(2n-1) {
color: $first-color;
}
span:nth-of-type(2n) {
color: $second-color;
}
Alternatively, your could use the #while directive:
$i: 1;
#while $i <= 7 {
.char#{$i}{
#include letter($first-color);
}
.char#{$i+1}{
#include letter($second-color);
}
$i: $i + 2;
}
Why don't you just use even and odd rules?
Like so you will be able to add infinite elements without touching your css every time.
$first-color: #666666;
$second-color: #0066CC;
#mixin letter($color){
color: $color;
}
.chars div:nth-child(even){
#include letter($first-color);
}
.chars div:nth-child(odd){
#include letter($second-color);
}
Here's an example on my Codepen.
Related
I have this for loop created like this:
.hero {
#for $i from 1 through 100 {
&.aspect-ratio--#{$i} {
#include aspect-ratio(16, $i);
}
&.aspect-ratio-sm--#{$i} {
#include media-breakpoint-up(sm) {
#include aspect-ratio(16, $i);
}
}
&.aspect-ratio-md--#{$i} {
#include media-breakpoint-up(md) {
#include aspect-ratio(16, $i);
}
}
&.aspect-ratio-lg--#{$i} {
#include media-breakpoint-up(lg) {
#include aspect-ratio(16, $i);
}
}
&.aspect-ratio-xl--#{$i} {
#include media-breakpoint-up(xl) {
#include aspect-ratio(16, $i);
}
}
}
}
When I create an element, like this:
<div class="hero aspect-ratio-md--6 aspect-ratio-sm--8 aspect-ratio--10"></div>
it's not respecting the order I declared my classes, so when I am in a md and above, instead of using aspect-ratio-md-6 it's actually using the aspect-ratio-10 instead.
like this:
Does anyone know what I am doing wrong?
Not sure why it voted down, but I figured this out.
It's because of how my loop was working, it was getting to 8 after 6, so that took precedence.
I changed my loop to this:
$breakpoints: sm, md, lg, xl, xxl;
.hero {
#each $breakpoint in $breakpoints {
#for $i from 1 through 100 {
&.aspect-ratio-#{$breakpoint}-#{$i} {
#include media-breakpoint-up($breakpoint) {
#include aspect-ratio(16, $i);
}
}
}
}
}
And this worked. Why? Because it looks through the breakpoints first meaning the last breakpoint will always take precedence over the first, then it loops from 1 to 100 and creates the classes, again, the later numbers taking precedence over the earlier numbers (not needed, but good to know)
Using Mixin, I want to determine a value between two entries and add it to a specific property.
Here is a dummy example:
#mixin min($property, $min1, $min2) {
#if ($min1 > $min2) {
$property: $min2;
}
#else {
$property: $min1;
}
}
.test {
#include min(width, 11px, 13px);
}
.test1 {
#include min(background-size, 30px, 13px);
}
.test2 {
#include min(height, 8px, 50px);
}
I would like to have the ouput:
width: 11px;
background-size: 13px;
height: 8px;
The problem is that $property: $min1; sets min1 value to property and I would like to return a literal.
How can I do that using mixin ?
You're almost there. You must use interpolation on the $property variable:
#mixin min($property, $min1, $min2) {
#if ($min1 > $min2) {
#{$property}: $min2;
}
#else {
#{$property}: $min1;
}
}
I created a SASS #mixin which contains #if conditions to assign styling to elements based on their z-index property to create some sort of elevation.
However what ever I am trying it will not work out.
I'm pretty sure I am doing something just slightly wrong that affects everything else.
I'd appreciate your feedback. Thanks in advance!
$background: #121212;
$surface: #1f1f1f;
$surface-shade_1: #282828;
$surface-shade_2: #303030;
%surface {
background-color: $surface;
}
%surface-shade_1 {
background-color: $surface-shade_1;
}
%surface-shade_2 {
background-color: $surface-shade_2;
}
#mixin elevation($elevationValue) {
#if $elevationValue>0 {
#extend %surface;
}
#else if $elevationValue>4 or $elevationValue=4 {
#extend %surface-shade_1;
}
#else if $elevationValue>8 or $elevationValue=8 {
#extend %surface-shade_2;
}
z-index: $elevationValue * 50;
}
nav {
#mixin elevation(4);
}
If you want to use #mixin inside the CSS files you can use like #include mixin-name and also use directly $elevationValue >= 4 instead of $elevationValue>4 or $elevationValue=4 it becomes much cleaner.
$background: #121212;
$surface: #1f1f1f;
$surface-shade_1: #282828;
$surface-shade_2: #303030;
%surface {
background-color: $surface;
}
%surface-shade_1 {
background-color: $surface-shade_1;
}
%surface-shade_2 {
background-color: $surface-shade_2;
}
#mixin elevation($elevationValue) {
#if $elevationValue > 0 {
#extend %surface;
}
#else if $elevationValue >= 4 {
#extend %surface-shade_1;
}
#else if $elevationValue >= 8 {
#extend %surface-shade_2;
}
z-index: $elevationValue * 50;
}
nav {
#include elevation(4);
}
I'm trying to loop through a list of values in Sass and use interpolation of the current key to dynamically output class names that utilize #include and #extend, respectively.
Here is a pen showing the problem, simplified. http://codepen.io/ghepting/pen/vBmLy
As you can see in the markup, I have tried including the "_" inside of the interpolated string as well as outside of it. Is there something I'm missing to work around this limitation of how Sass supports interpolation?
(Note: the OP's pen has disappeared. This is not the original code found in the pen, but a rough approximation of the problem)
$error-light: red;
$error-dark: darken(red, 10%);
$success-light: green;
$success-dark: darken(green, 10%);
$dialogs: error, success;
#each $d in $dialogs {
.#{$d} {
background: $#{$d}-light;
}
}
Interpolation doesn't work on mixins or variables at this point in time. You'll have to come up with a different way to achieve your goal.
As of Sass 3.3, you can use mappings for this purpose for variables:
$dialogs:
( error:
( light: red
, dark: darken(red, 10%)
)
, success:
( light: green
, dark: darken(green, 10%)
)
);
#each $name, $colors in $dialogs {
.#{$name} {
color: map-get($colors, dark);
}
}
And for functions:
#function green() {
#return lighten(green, 10%);
}
#function red() {
#return lighten(red, 10%);
}
#mixin my-bg($function-name) {
background: call($function-name);
}
.foo {
#include my-bg('red');
}
Alternative workaround (for a particular use case):
https://sass-lang.com/documentation/at-rules/mixin#passing-arbitrary-arguments
💡 Fun fact:
Because an argument list keeps track of both positional and keyword arguments, you use it to pass both at once to another mixin. That makes it super easy to define an alias for a mixin!
If you are interested in mixin interpolation because you have a group of mixins, like this:
//_mixins.scss
#mixin text-style-1($args...){ //sass here }
#mixin text-style-2($args...){ //sass here }
#mixin text-style-3($args...){ //sass here }
//_text.scss
.text-style-1 {
#include text-style-1;
}
.text-style-1-contrast {
#include text-style-1($contrast: true);
}
.text-style-2 {
#include text-style-2;
}
.text-style-2-contrast {
#include text-style-2($contrast: true);
}
We can take advantage of passing arbitrary arguments and use an alias for the group:
//_mixins.scss
#mixin text-style-1($args...){ //sass here }
#mixin text-style-2($args...){ //sass here }
#mixin text-style-3($args...){ //sass here }
#mixin text($mixin, $args...) {
#if $mixin == 'style-1' { #include text-style-1($args...); }
#else if $mixin == 'style-2' { #include text-style-2($args...); }
#else if $mixin == 'style-3' { #include text-style-3($args...); }
}
//_text.scss
$text-styles: 'style-1', 'style-2', 'style-3';
#each $style in $text-styles {
.text-#{$style} {
#include text($style);
}
.text-#{$style}-contrast {
#include text($style, $contrast: true);
}
}
Ran into this issue of trying to include an interpolated variable inside a mixin and was able to resolve it with placeholders:
%color-scheme-dark-bg-1 { background-color: #4e5163; }
%color-scheme-dark-color-1 { color: #4e5163 !important; }
%color-scheme-light-bg-1 { background-color: #c7c8ce; }
%color-scheme-dark-bg-2 { background-color: #fd6839; }
%color-scheme-dark-color-2 { color: #fd6839 !important; }
%color-scheme-light-bg-2 { background-color: #fecfc1; }
.card_color {
#mixin CardColorScheme($arg: 1) {
.borderPercent {
#extend %color-scheme-dark-bg-#{$arg};
}
.border {
#extend %color-scheme-light-bg-#{$arg};
}
ul li:before {
#extend %color-scheme-dark-color-#{$arg};
}
.percent {
#extend %color-scheme-dark-color-#{$arg};
}
.heading {
#extend %color-scheme-dark-color-#{$arg};
}
}
&--scheme {
&-1 {
#include CardColorScheme(1);
}
&-2 {
#include CardColorScheme(2);
}
}
}
Hat tip to: https://krasimirtsonev.com/blog/article/SASS-interpolation-in-a-name-of-variable-nest-variables-within-variables
I tried to make the following code look fancier with an #each or a #for loop (without any usable result).
.btn[data-btn-color="black"] {
#include colored-btn($black);
}
.btn[data-btn-color="blue"] {
#include colored-btn($blue);
}
.btn[data-btn-color="red"] {
#include colored-btn($red);
}
// ... and more colors ...
My current approach is to take value from the variable to use it as the value for the data-btn-color attribute and put that snippet into an #each loop.
Something like
#each $color in ($black, $blue) {
#include colored-btn($color);
}
which compiles into:
.btn[data-btn-color="black"] {
background-color: #000; // $black
}
.btn[data-btn-color="blue"] {
background-color: #00f; // $blue
}
Is there any function, which allows me to do such a thing?
You were so close! You don't want the () around what you want to go through in #each. I think Sass would just see what you have as one list item with a two item list inside.
Here is what I think you're trying to do:
$red: #f00;
$blue: #00f;
$black: #000;
$colors: red $red, blue $blue, black $black;
#mixin colored-button($background-color: #000){
background-color: $background-color;
}
#each $color in $colors {
$name: nth($color, 1);
$hex: nth($color, 2);
.btn[data-btn-color="#{$name}"]{
#include colored-button($hex);
}
}
Which would result in:
.btn[data-btn-color="red"] {
background-color: red; }
.btn[data-btn-color="blue"] {
background-color: blue; }
.btn[data-btn-color="black"] {
background-color: black; }