Output lighter and darker colour variants - sass

I want to output some utility classes and I can't seem to get the lighter and darker tones of my base color to output both darker and lighter tones. I am new to Scss but this is what I have:
$aqua: #00ffff;
$color-map: (
background-color-aqua-light: ($aqua, background-color, lighten,),
color-aqua-light: ($aqua, color, lighten),
background-color-aqua-dark: ($aqua, background-color, darken),
color-aqua-dark: ($aqua, color, darken)
);
#each $color-class, $colour-variables in $color-map {
$class-name: nth($color-class, 1);
$color-name: nth($colour-variables, 1);
$color-type: nth($colour-variables, 2);
$color-brightness: nth($colour-variables, 3);
#for $i from 20 through 100{
#if $i % 10 == 0{
$percentage: $i*0.5%;
.#{$class-name}-#{$i}{
#{$color-type}: #{$color-brightness}($color-name, $percentage);
}
}
}
}

It looks like you're generating the method name in the CSS:
So this SCSS
#{$color-type}: #{$color-brightness}($color-name, $percentage);
Becomes this CSS
.background-color-aqua-light-40 {
background-color: lighten(#00ffff, 20%);
}
To my knowledge, you can't interpolate a SASS method name and get SASS to interpret it. But. I think you can (maybe less elegantly) get around that limitation with the #if and #elseif rules in your #for loop.
#for $i from 20 through 100 {
#if $i % 10 == 0 {
$percentage: $i*0.5%;
.#{$class-name}-#{$i} {
#if ( $color-brightness == lighten ) {
#{$color-type}: lighten($color-name, $percentage);
} #elseif ( $color-brightness == darken ) {
#{$color-type}: darken($color-name, $percentage);
}
}
}
}
EDIT: FWIW, I tested the #if/#elseif solution on sassmeister.com and it seems to crank out the CSS you are after.

Related

Sass mix() function is giving error with valid color values

_theme-var.scss
//color palette
$colors:(
"primary":#ff0000,
"secondary":#898989,
"dark":#360000,
"light":#ffaeae,
"white":#fff
);
style.scss
#import "./theme-var";
#each $key,$val in $colors{
.text-#{$key}-color{
color: $val;
}
.bg-#{$key}-color{
background-color:$val;
}
#for $i from 1 through 9{
.text-#{$key}-color-light-#{$i}{
color: mix(#ffff, #{$val},$i*10); // getting error for this line
}
}
}
ERROR
It says that argument $color-1 of mix($color-1, $color-2, $weight: 50%) must be a color, I am passing color and also $val contains valid hax color what could be the reason for error?
ERROR SCREENSHOT
You need to remove the interpolation on #{$val}. The variable is already a color and the interpolation seems to convert it to something else, that's why you get this error.
#for $i from 1 through 9 {
.text-#{$key}-color-light-#{$i}{
color: mix(#ffff, $val, $i*10);
}
}

SASS #each and #for generate nothing

This code does not generate error but classes was not created.
Do someone have an idea ?
$properties: margin, padding, height, margin-top, margin-bottom, border,
height;
#each $property in $properties {
#for $size from 1 through 500 {
.#{$property}-#{$size} {
$property: #{$size}px;
}
}
}
You also need to interpolate the css-property: #{$property}: #{$size}px;

SASS mixing and passing a variable string that's a function name

I'm expanding out a SASS mixin for generating background colours.
Here's my mixin:
#mixin color-columns ($count, $baseName, $startcolor) {
$loop_color : $startcolor;
#for $i from 0 through $count {
$loop_color : darken($loop_color, 8%);
.#{$baseName}-#{$i} {
background-color : $loop_color;
}
}
}
And i use it like this:
#include color-columns(5,'col', $blue);
What I want to do is pass in either 'darken' or 'lighten' as a variable so i can control with SASS colour function. Something like this:
#mixin color-columns ($count, $baseName, $startcolor, $change: 'darken') {
$loop_color : $startcolor;
#for $i from 0 through $count {
$loop_color : $change($loop_color, 8%);
.#{$baseName}-#{$i} {
background-color : $loop_color;
}
}
}
When i try that, my CSS for the first column is like this:
background-color: darken darken #005387, 8%, 8%;
I'm missing the connection on passing a variable that swaps the function.
Currently there is no support for defining dynamic function names. It has been requested several years ago and there is even an open pull request for this functionality but it is not yet merged.
However, it is possible to dynamically call a function with the built-in call($function, $args...) function. It allows you to avoid if-else cascades and can be used in your example like this:
$loop_color : call($change, $loop_color, 8%);
I ended up adding an #if to get this to work:
#mixin color-columns ($count, $startcolor, $start : darken) {
$loop_color : $startcolor;
#if $start == 'lighten' {
#for $i from 0 through $count {
$loop_color : lighten($loop_color, 5%);
.conBG-#{$i} {
background-color : $loop_color;
}
}
}
#else {
#for $i from 0 through $count {
$loop_color : darken($loop_color, 5%);
.conBG-#{$i} {
background-color : $loop_color;
}
}
}
}

Conditionally output a part of SCSS rule selector

I would like to specify an additional default shortcut class to a set of classes, similarly to that
#each $pos, $some-css-rules in ("left": ..., "right": ..., ...) {
#if $pos == "left" {
.block,
}
.block-#($pos) {
...
}
}
that would be outputted as
.block,
.block-left {
...
}
.block-right {
...
}
However, it will stumble over .block, syntax error.
.block-left cannot be replaced here with .block.left because $pos will collide with existing classes (.left, etc).
I would prefer to avoid .block { #extend .block-left } if possible, there is a considerable amount of similar rules that will gain a lot of WET code this way.
Is there a way to conditionally output a part of rule selector? How can both SCSS and CSS be kept DRY in a pattern like that?
I'm not sure if I understand the question but I achieve the output CSS based on your code. I put the #if directive inside the selector to compare with $pos variable. Here is my code:
SASS
#each $pos, $some-css-rules in ("left": red, "right": blue) {
.block-#{$pos} {
#if $pos == "left" {
#at-root .block, &{
color:$some-css-rules;
}
}
#else{
color:$some-css-rules;
}
}
}
Output
.block, .block-left {
color: red;
}
.block-right {
color: blue;
}

SASS mixin error because of Deprecation

I am using the following mixin for REM conversions
https://gist.github.com/bitmanic/1134548
Since the latest SASS update the mixin is now showing an error:
// If the value is zero or a string or a color, return unchanged input
#if $value == 0 or type-of($value) == "string" or type-of($value) == "color" {
$rem-values: append($rem-values, $value); }
#else {
$rem-values: append($rem-values, $value / $baseline-rem); } }
The result of 0px == 0 will be false in future releases of Sass. Unitless numbers will no longer be equal to the same numbers with units.
I am a bit new to SASS, can someone help trouble shoot this?
Are you sure it's an actual error rather than a warning?
The warning is likely in reference to this issue. The jist of the problem being fixed here is where 1px == 1, which is inherently untrue.
Realistically, you should always use 0 for lengths rather than 0px, despite the fact that they are equal, simply because you would be saving a few bytes. You should be able to strip off the unit and then perform the comparison:
$baseline_px: 10px;
#mixin rem($property, $px_values) {
// Convert the baseline into rems
$baseline_rem: ($baseline_px / 1rem);
// Print the first line in pixel values
#{$property}: $px_values;
// Create an empty list that we can dump values into
$rem_values: ();
#each $value in $px_values {
// If the value is zero, return 0
#if $value / ($value * 0 + 1) {
$rem_values: append($rem_values, $value);
zero: $value;
}
// If the value is not zero, convert it from px to rem
#else {
$rem_values: append($rem_values, ($value / $baseline_rem) );
not-zero: $value
}
}
// Return the property and its list of converted values
#{$property}: $rem_values;
}
.foo {
#include rem(font-size, 10px);
#include rem(border-width, 0px);
#include rem(border-width, 0);
}
Alternately, you could check if it is within a list of zero values:
#if index((0, 0px), $value) {
// do 0 related stuff
}

Resources