Sass function using color operations - css

I'm trying to build a function to automate hover state operations. So gar I have this
$switch-element-hover: 20% !default;
$switch-element-operation: "lighten" !default;
#function generate-hover-state($color) { #return
#{$switch-element-operation}($color, $switch-element-hover); }
Then I try to use it like this:
&:hover {
background-color: generate-hover-state($background);
}
Now I managed to compile it but the output looks weird:
background-color: lighten#626262, 20%;
Also I have tried using unquote as suggested by the tool but it doesn't seem to work.
Does anyone have any idea how to do this?

Solved it.
The answer laid in the #call method:
http://sass-lang.com/documentation/Sass/Script/Functions.html#call-instance_method
// Hover state function
#function generate-hover-state($color) {
#return call($switch-element-operation, $color, $switch-element-hover);
}

Related

Is there a way to define SASS variables in a" [data='value'] {}", or only regular CSS variables?

I want to export "$var" like variables defined as "--var" variables from a Scss file to be used in other files with some scss functions such as "darken()", but it says its not a color.
I'm coding a Vue/Vite website and implementing a theme-change button, that will write data at the HTML tag, and use it to define the theme.
<html lang="en" data-theme="dark"> ... </html>
The base.scss looks like this:
[data-theme="dark"] {
--primary: #c6c7df;
--secondary: #c95d63;
--text-light: #e2ebf5;
}
[data-theme="light"] {
--primary: #26298d;
--secondary: #c95d63;
--text-light: #2c3e50;
}
$primary: var(--primary);
$secondary: var(--secondary);
$text-light: var(--text-light);
I can use the "$var"-like variable at the end of the file, but when I use it inside a "darken($primary, 10%)" function, it gives the following error:
Error: $color: var(--primary) is not a color.
I know it's because I defined it as a CSS variable but if I define the variable inside the "[theme] {}" thing, it doesn't get innitialized and throws the error "Undefined variable"
I know it's a niche question, and I could use something like this, but I wish I could just export it as a scss variable.
Thank you very much.
Of course we cannot make a CSS variable lighten or darken. Think about, What will happen to the Name of CSS variable in the output?
So we have to define all CSS variables and assign desired colors, Before using them.
Solution
For this purpose, you can automatically create the list of CSS variables by #each and create a manual function by #function for easy use. This way gives us a standard css output and the best experience in Sass coding.
// Theme defines area:
$theme-colors:(
"primary": #940fe0,
"secondary": #e49f38,
"warning": #ffe600,
"info": #165ad6
);
$darken-percent: 20%;
$lighten-percent: 20%;
// Functions area:
:root {
#each $name, $color in $theme-colors {
$lighten: lighten($color, $lighten-percent);
$darken: darken($color, $darken-percent);
--color-#{$name}: #{$color};
--color-#{$name}-light: #{$lighten};
--color-#{$name}-dark: #{$darken};
}
}
#function cl($name, $color-tone) {
#if not map-get($theme-colors, $name+''){
#error "`#{$name}` is not defined in Colors Theme";
}
#if $color-tone == d {
#return var(--color-#{$name}-dark);
}
#if $color-tone == l {
#return var(--color-#{$name}-light);
}
#else{
#return var(--color-#{$name});
}
}
// Our custom function usage:
// Use 'b' to return Base color. Ex: cl(primary,b)
// Use 'l' to return Lighten color. Ex: cl(primary,l)
// Use 'd' to return Darken color. Ex: cl(primary,d)
.test {
color: cl(primary,b);
color: cl(warning,l);
}
Compiled css result:
:root {
--color-primary: #940fe0;
--color-primary-light: #bf61f4;
--color-primary-dark: #550980;
--color-secondary: #e49f38;
--color-secondary-light: #f0ca92;
--color-secondary-dark: #a06916;
--color-warning: #ffe600;
--color-warning-light: #fff066;
--color-warning-dark: #998a00;
--color-info: #165ad6;
--color-info-light: #6395ef;
--color-info-dark: #0c337a;
}
.test {
color: var(--color-primary);
color: var(--color-warning-light);

Using sass selector functions inside a reusable function

I'm looking at solving a specific problem with SASS - I want to append a pseudo-class to the selectors of a lot of old legacy styles, and ideally I'd like to do it in a DRY way.
I saw that sass enables you to append to a selectors using the selector-append function - however, I can't seem to figure out a way to write some sort of reusable function in sass that calls such a function to modify a selector.
Here's what I've tried:
#function optOut($selector) {
#return selector-append($selector, ":not(:where(*.opt-out))");
}
optOut(div) {
color: black;
}
But, depending on the sass compiler I use, it either does not compile or just compiles to:
optOut(div) {
color: black;
}
I'd like it to compile to this:
div:not(:where(*.opt-out)) {
color: black;
}
Any help is greatly appreciated - thank you so much for your time and knowledge.
You just need to interpolate the return value of the function like so:
#function optOut($selector) {
#return selector-append($selector, ":not(:where(*.opt-out))");
}
#{optOut(div)} {
color: black;
}

SASS Simple function to convert HEX color into RGB as a string without alpha

I am looking for simple function in SASS that simply convert HEX color into RGB as a string.
I was googling, but without lucky. Maybe because there is not any native function in SASS? Sure, there is rgba() function, but I dont wanna rgba( ... ) piece. Simply the RGB string.
Example
Input
$color-bg: #637b9a;
$color-bg-light: lighten($color-bg, 25%);
$color-bg-light-rgb: hex2rgb($color-bg-light); // Functon that I am looking for
:root {
--color-body-bg-light: $color-bg-light;
--color-body-bg-light-rgb: $color-bg-light-rgb;
}
body {
color: var(--color-body-bg-light);
background-color: rgba(var(--color-body-bg-light-rgb), 0.8);
}
Output
:root {
--color-body-bg-light: #237b9a;
--color-body-bg-light-rgb: 44, 123, 154;
}
body {
color: var(--color-body-bg-light);
background-color: rgba(var(--color-body-bg-light-rgb), 0.8);
}
You can write the function like this:
#use "sass:color";
#function hex2rgb($hex) {
#return red($hex), green($hex), blue($hex);
}
But the problem is sass could not parse the variables for html custom properties.
So this line --color-body-bg-light: $color-bg-light; won't work.
At the end, you will get this:
:root {
--color-body-bg-light: $color-bg-light;
--color-body-bg-light-rgb: $color-bg-light-rgb;
}
You can't do that with Sass but you can use JavaScript to get the desired result.

cannot assign SCSS values to css custom properties (css variables)

To ensure readability and maintainability, I would like to declare several values like colors for example, but only once.
The problem I have is that it seems impossible to assign the result of a sass function or even simple variables directly to css variable.
.some-selector {
--my-css-variable: $my-color; // nope
--my-css-variable: mySassFunction(); // nope
--my-css-variable: transparentize($my-color, .5); // nope
--my-css-variable: copy-pasted-value; // alright
}
I can't seem to find any answer on search engines, always finding irrelevant topics at best.
Could you help me?
Try with interpolation #{...}
$my-color: #fff;
#function myFunction() {
#return #000;
}
.some-selector {
--my-css-variable: #{$my-color};
/* output: --my-css-variable: #fff; */
--my-css-variable: #{myFunction()};
/* output: --my-css-variable: #000; */
}

Generating dynamic color map in SASS

I'm trying to generate a rather automated system to define colours in SASS. I have a list of colours, defined with a hexidecimal value (like so: $color--deep-ocean: #123143;) and a global $colors: (); definition.
I then want to create their RGBA values dynamically, and given variable interpolation isn't an option in SASS, I've tried my hands at maps.
The idea is to feed a set-color function a name and a color to populate my $colors variable with map-merge, which I can then retrieve with get-color. Here below are my two function definitions and how I'm trying to use them:
#function color-set($name, $hex) {
$submap: (hex: $hex);
#for $o from 0 to 20 { // Going in increments of 5
$percentage-decimal: $o*0.05;
$percentage: $o*5;
$submap: map-merge($submap, ($percentage: rgba($hex, $percentage-decimal)));
}
$colors: map-merge($colors, ($name: $submap));
/* We should then have a map that looks like this:
$colors: (colorname: (
hex: #000000,
0: rgba(0,0,0,0),
5: rgba(0,0,0,.05),
// and so on…
100: rgba(0,0,0,1)
)
)
… right? */
}
#function color-get($name, $opacity: hex) {
#if $opacity != hex { // Returns RGBA value
#return map-get(map-get($colors,$name), $opacity);
}
#else { // Returns hexidecimal value
#return map-get(map-get($colors,$name), hex);
}
}
Please let me know if my functions are confusing! I'll try to comment them better.
This is how I'm trying to define a colour (part of _variables.scss):
color-set(bkgrnd, $color--deep-ocean);
And here's how I'm trying to use my colours:
body { // These colours have been defined, too …supposedly
background-color: color-get(bkgrnd, 80);
color: color-get(white);
}
Here is the error I get on _variables.scss:
Invalid CSS after "...ackground color": expected 1 selector or at-rule, was "color-set(bkgrnd, $"
So I feel like I'm missing something. I've had my head wrapped around this for four hours and I'm going mad. It's probably super simple stuff but I can't seem to figure it out. I use SASS casually, so I might not be aware of some syntax issue but if anyone has a clue about how to fix this, I'd be quite grateful.
Have a nice day and thank you for taking the time to read my post!
Regards,
Chris
PS: I compile this in Brackets with the Brackets SASS plugin, if ever that information is relevant.
After digging some more, I found out what my issue was. SASS functions must have a #return directive in order to work. As a result, I updated my color-set function, and added #return $colors; at the end of it. Then, I just needed to give some directive so the function wouldn't be called "out of the blue", so I assigned my $colors variable to it like such:
$colors: color-set(bkgrnd, $color--deep-ocean);
I think it might be a bit repetitive to reassign $colors to itself all the time, but given this only affects performance during compilation, and not on my final CSS file, I can get away with it. There might be a better way (and I'm all ears if you have an idea!) but for now this fits my needs just fine.
And like that, I am able to handle my colors using maps. Thanks to anyone who had a look at my problem, and sorry for posting this - I should have taken some time to cool down and think some more. I hope this helps someone else who is stumbling on the same problem to fix their issues!
Take care,
Chris
PS: If ever you wanted it, below is the full code.
_colors.scss
$color--deep-ocean: #123143;
$color--yellow: #ffce00;
// And so on, and so forth…
_mixins.scss
#function color-set($name, $hexval) {
#return map-merge($colors, ($name: $hexval));
}
#function color-get($name, $opacity: hex) {
#if $opacity != hex { // Returns RGBA value
$opacity-decimal: $opacity/100;
#return rgba(map-get($colors,$name), $opacity-decimal);
}
#else { // Returns hexidecimal value
#return map-get($colors, $name);
}
}
_variables.scss
$colors: color-set(bkgrnd, $color--deep-ocean);
$colors: color-set(main, $color--yellow);
// And so on, and so forth again…
Usage example:
body {
background-color: color-get(bkgrnd); // Returns #123143
color: color-get(main); // Returns #ffce00
}
button {
border: 2px solid color-get(main, 50); // Returns rgba(255, 206, 0, 0.5)
}

Resources