I'm developing a project using LESS as compiler for my CSS.
I have already a fully working loop that sets the background color properly.
My question is this:
With my current code, when i try to use darken property, the compiling result is this:
SyntaxError:error evaluating function darken: Object # has
no method 'toHSL'
and the code is this one:
#colors:
"008B8B",
"00CDCD",
"00EEEE";
/* Colors and background loop (based on colors.less arrays) */
.loop-colors(#index) when (#index > 0){ // loop to generate rules for each color
.loop-colors(#index - 1);// call for the next iteration
#color: e(extract(#colors, #index));
#hexColor: ~'##{color}';
#border: 1px solid darken(#hexColor, 5%);
&.col-#{color}{
background: #hexColor;
border:#border;
}
}
i have no idea why this is not good.
I mean, i think is because the list of color doesn't have the "#" before every color, but just because i'm using it on the css class as well, i can't add it to #colors, so i have to add it later.
I don't know if and why adding the "#" later will affect the darken property and how.
Thanks
As mentioned by #seven-phases-max, ~'##{color}' will not create a color but a string. To convert a string to a color, you can use color function.
#colors:
"008B8B",
"00CDCD",
"00EEEE";
/* Colors and background loop (based on colors.less arrays) */
.loop-colors(#index) when (#index > 0) { // loop to generate rules for each color
.loop-colors(#index - 1);// call for the next iteration
#color: e(extract(#colors, #index));
#hexColor: ~'##{color}';
#border: 1px solid darken(color(#hexColor), 5%);
&.col-#{color} {
background: #hexColor;
border: #border;
}
}
Related
I need to be able to use CSS variables because I need to have an hover effect (background-color) to be customizable by my VueJs app.
But my CSS stylesheet should have a default value, which is stored in a nested SCSS map. (map-getter is a function which returns values from nested maps)
I know that my SCSS code works, because I get the intended result when I do this:
.theme--dark .AppNavTile:hover {
background-color: map-getter($theme-dark, AppNav, hover);
//returns background-color: rgba(255, 255, 255, 0.87); in my browser's console
}
In order to use CSS variables, I can modify the code as follows:
.theme--dark .AppNavTile:hover {
--hover-bg-color: red;
background-color: var(--hover-bg-color);
}
It works fine and I have a red background when hovering the element.
Then I try to combine both:
.theme--dark .AppNavTile:hover {
--hover-bg-color: map-getter($theme-dark, AppNav, hover);
background-color: var(--hover-bg-color);
}
According to by browser's console, this returns the following:
.theme--dark .AppNavTile:hover {
--hover-bg-color: map-getter($theme-dark, AppNav, hover);
background-color: var(--hover-bg-color);
}
So it seems that the SCSS code remains uncompiled in the CSS variable. Is there any way around it?
Thanks!
The "problem" with CSS variables is they can have any value – why map-getter($theme-dark, AppNav, hover) is rendered as is. To instruct SCSS that this is actual SCSS code and not a random string you need to use interpolation (like if you use SCSS variables inside calc):
--hover-bg-color: #{map-getter($theme-dark, AppNav, hover)};
I'm trying to call a mixin as an argument in another mixin but I get a syntax error. There's no variables in the offending mixin call, just arguments.
I'm not sure if this is possible. The answers I've seen on here seem to be either hacks or to be dealing with variables and strings as arguments.
Less CSS
// color variables for user's color
#userColor: #13acae;
#darkUser: hsl(hue(#userColor), saturation(#userColor), lightness(tint(#userColor, 30%)));
#lightUser: hsl(hue(#userColor), saturation(#userColor), lightness(shade(#userColor, 30%)));
// color mixin to alter user's color using Less 'darken' and 'contrast' functions
.contrastColorDark(#percent) { color: darken(contrast(#userColor, #darkUser, #lightUser), #percent); }
// border mixin
.border(#width, #color) { border: #width solid #color; }
// CSS rule using both mixins
.thing {
.border(1px, .contrastColorDark(10%));
}
Error (at the dot before .contrastColorDark(10%) )
SyntaxError: expected ')' got '.'
What I am trying to achieve: I am trying to get the box border color to match certain elements inside it that are using the contrast mixin.
As discussed in comments, Less mixins are not functions and the mixin calls cannot return any value. Because of this, one mixin (or its output value) cannot be passed as an argument to another mixin.
Having said that, we can still set a variable within a mixin, call the mixin within each selector block where it is required and make use of the variable defined within it. The mixin call effectively exposes the variable defined within it to the parent scope.
Below is a sample snippet which would call the contrast mixin and assign the calculated value as the text color and border color of the element.
// color variables for user's color
#userColor: #13acae;
#darkUser: hsl(hue(#userColor), saturation(#userColor), lightness(tint(#userColor, 30%)));
#lightUser: hsl(hue(#userColor), saturation(#userColor), lightness(shade(#userColor, 30%)));
// color mixin to alter user's color using Less 'darken' and 'contrast' functions
.contrastColorDark(#percent) {
#color: darken(contrast(#userColor, #darkUser, #lightUser), #percent);
//color: darken(contrast(#userColor, #darkUser, #lightUser), #percent);
}
// border mixin
.border(#width, #color) {
border: #width solid #color;
}
// CSS rule using both mixins
.thing {
.contrastColorDark(10%);
color: #color;
.border(1px, #color);
}
.thing2 {
.contrastColorDark(50%);
color: #color;
.border(1px, #color);
}
Using SASS, I am trying to create a dynamic linear-gradient, so if I have an array of colors, I would like to loop through it and add each color to the gradient.
#import "compass";
$colors: red green blue;
$numColors: length($colors);
div {
$g: nth($colors, 1);
#for $h from 2 to ($numColors + 1) {
$g: $g , nth($colors, $h);
}
border: $g;
background: linear-gradient($g);
}
This results in the following error
At least two color stops are required for a linear-gradient
Removing the background parameter will compile, and looks like this
border: red, green, blue;
(I know that's not a valid border, I just wanted to "trace" out $g)
How can I dynamically iterate through an array and create a linear gradient?
You have 2 problems here.
linear-gradient is a custom Compass function, that's what's generating that error. As such, it expects a specific number of arguments.
You're not creating a list with 3 elements in it, you're creating a list with a single element in it that looks something like this: [[red, green], blue]. The first element of the list is a list containing 2 elements.
What you're needing here is the append() function:
div {
$g: nth($colors, 1);
#for $h from 2 to ($numColors + 1) {
$g: append($g , nth($colors, $h));
}
border: $g;
background: linear-gradient($g);
}
That will give you your expected output:
div {
border: red green blue;
background: linear-gradient(#ff0000, #008000, #0000ff);
}
I'm developing a project using LESS as compiler for my CSS.
I have already a fully working loop that sets the background color properly.
My question is this:
With my current code, when i try to use darken property, the compiling result is this:
SyntaxError:error evaluating function darken: Object # has
no method 'toHSL'
and the code is this one:
#colors:
"008B8B",
"00CDCD",
"00EEEE";
/* Colors and background loop (based on colors.less arrays) */
.loop-colors(#index) when (#index > 0){ // loop to generate rules for each color
.loop-colors(#index - 1);// call for the next iteration
#color: e(extract(#colors, #index));
#hexColor: ~'##{color}';
#border: 1px solid darken(#hexColor, 5%);
&.col-#{color}{
background: #hexColor;
border:#border;
}
}
i have no idea why this is not good.
I mean, i think is because the list of color doesn't have the "#" before every color, but just because i'm using it on the css class as well, i can't add it to #colors, so i have to add it later.
I don't know if and why adding the "#" later will affect the darken property and how.
Thanks
As mentioned by #seven-phases-max, ~'##{color}' will not create a color but a string. To convert a string to a color, you can use color function.
#colors:
"008B8B",
"00CDCD",
"00EEEE";
/* Colors and background loop (based on colors.less arrays) */
.loop-colors(#index) when (#index > 0) { // loop to generate rules for each color
.loop-colors(#index - 1);// call for the next iteration
#color: e(extract(#colors, #index));
#hexColor: ~'##{color}';
#border: 1px solid darken(color(#hexColor), 5%);
&.col-#{color} {
background: #hexColor;
border: #border;
}
}
Does anyone know how to do what I am attempting to do here?
#theme (dark) {#primary: black;}
#theme (light) {#primary: white;}
#theme (#_) {#primary: yellow;}
#name: dark;
#theme(#name);
.rule {
color: #primary;
}
I am trying to define a few "themes" which will have colors and images (possibly) that will be used throughout the various Less files. I have made do in the past with defining them globally and commenting out those that are not in use, but I am trying to see if there are people who have found better strategies in Less than what I have.
I had at one point found a feature that used to be (?) a part of Less but it doesn't seem to work.
.theme {
#color: red;
}
.rule {
color: .theme > #color;
}
This would be great, if it worked.
After a bit of messing with LESSCSS, I've come up with a reasonable way to change all variables based on a single #theme variable.
The trick is to use variable interpolation to specify a variable reference to a variable.
//this can be either "dark" or "light"
#theme: dark;
#theme-primary: "#{theme}-primary"; //this will evaluate to "dark-primary"
#theme-secondary: "#{theme}-secondary"; //this will evaluate to "dark-secondary"
#dark-primary: #F00;
#dark-secondary: #000;
#light-primary: #333;
#light-secondary: #FFF;
body {
//#theme-secondary evaluates to "dark-secondary"
//#dark-secondary evalutates to #000
background-color: ##theme-secondary;
//#theme-primary evaluates to "dark-primary"
//#dark-primary evaluates to #F00
color: ##theme-primary;
}
Older version
While I don't know of an easy way to conditionally define variables, if you're going to change one word and change a color theme, you might as well change an import statement:
#import ’themes/dark.less’;
//#import ’themes/light.less’;