Dynamic Variable Names in LESS CSS - css

I have been trying this for a while, looking at other answers, but to no avail. Hopefully someone can help me.
I am trying to generate some dynamic variable names within a mixin.
The variables are already defined:
#horizontal-default-color: #fff;
#horizontal-inverse-color: #000;
etc..
The mixin I want would be something like this:
.horizontal-variant(#variant) {
color: #{horizontal-#{#variant}-color}
}
And the result I am expecting, when called:
.horizontal-default{
.horizontal-variant(~"default");
}
.horizontal-inverse{
.horizontal-variant(~"inverse");
}
is
.horizontal-default {color: #fff}
.horizontal-inverse {color: #000}
Unfortunately I run into errors every time.
I know this can be done, I have seen it being used in Font Awesome LESS where #{fa-css-prefix} is defined in variables. I am just having trouble transporting the same solution in my project.
You can try testing the code at http://lesstester.com/

You can use Variable Names. And I've tested the code at http://lesstester.com/, it works.
#horizontal-default-color: #fff;
#horizontal-inverse-color: #000;
.horizontal-variant(#variant) {
#color: "horizontal-#{variant}-color";
color: ##color;
}
.horizontal-default{
.horizontal-variant(default);
}
.horizontal-inverse{
.horizontal-variant(inverse);
}

Related

How to combine LESS color functions and CSS Variables?

In my project I have a CSS custom variables like this:
:root {
--primary-color: #e04c4c;
--secondary-color: #2c2c5e;
--text-color: #d67900;
}
In my LESS files I have used LESS color functions to get more colors base on its primary and secondary. This is how its look like:
.component1 {
background: darken(--primary-color, 10%);
}
.component2 {
background: lighten(--secondary-color, 5%);
}
But when I compile this, it gives an error like this?
// Undefined_methodError: error evaluating function darken: //
Object # has no method 'toHSL'
When googling I found a solution for SASS, but not for LESS.
Can anybody tell me is there any possible workaround for this particular case?
Thank you.

LESS Declare variables using class names?

I have a button class that sets up padding etc for an element, followed by a class that defines a background colour.
.button {
padding: 0.5em 1em;
text-transform: uppercase;
color: #fff;
&.green {
background:#green; //declared previously
}
// ... more colours
}
Is it possible to declare the #green variable as the class name? This would save me having to copy/paste the &.green block for each colour I am wanting to use.
I've not been able to find anything the docs regarding this sort of selector, but something along the lines of:
&.(green|blue|red) {
background: #{$1};
}
which would generate the following:
.button.green{background:#00ff00;}
.button.blue{background:#0000ff;}
.button.red{background:#ff0000;}
You could achieve this by having a variable with the required list of colors, a loop to create the required rules and selector interpolation like shown below.
#colors: "green","blue","orange","red","yellow"; // the list of colors required
button {
padding: 0.5em 1em;
text-transform: uppercase;
.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)); // pick the color value from the list one by one based on current index
&.#{color} {
background:#color;
}
}
.loop-colors(length(#colors));
}
Codepen Demo
Note: As mentioned in comments, LESS PHP is quite outdated and hence some of the new features offered by LESS (with respect to loops) are not supported by it. It could be overcome by doing the work-around mentioned in this answer.
You could also adopt an approach similar to the one mentioned by seven-phases-max in this answer (2nd option). That one achieves a similar effect without using loops.

less css variables with color name

I'm trying to create a few dynamics classes width Less css.
The idea is use in html this class:
.color-white{
color: white !important;
}
I created this sintaxis in Less:
.change-color(#which; #color){
.color-#{which}{
color:#color !important;
}
.background-#{which}{
background-color:#color !important;
}
}
So, with this I want to take my idea :D
.change-color(#which: white; #color: white);
But, that is the problem, I have this:
.color-#ffffff{
color:#fff!important
}
.background-#ffffff{
background-color:#fff!important
}
How can I use "white" as string and not as hex color.
Thanks.
Call this way instead:
.change-color(#which: ~'white'; #color: ~'white');
Though I think it would be better to just create a class called .color-red explicitly rather than make things more unreadable for little reason.

Updating a Variable through a Mixin

So lets say I set the background of 10 elements on the page to #base, then a user lands on the "Foo" page which has the class on the body of the page.
How does one update the #base via a css declaration? I understand that variables are local to a function (or css declaration) but there must be a method to do this! (would make styling alternative pages so easy!)
#base: #00000;
body.foo{
#base = #FFF;
}
LESS is a Preprocessor so...
...it all has to be precompiled into CSS ahead of time. That means all possible class combinations need to be made into valid CSS ahead of time. If you wanted something like this, you would need to do something like the following in your LESS:
LESS
#base: #000000;
.setColorOptions(#className: ~'', #base: #base) {
#classDot: escape(`('#{className}' == '' ? '' : '.')`);
#class: escape(#className);
body#{classDot}#{class} {
someElement {color: #base;}
.someClass {color: #base;}
// etc.
}
}
.setColorOptions();
.setColorOptions(foo, #fff);
.setColorOptions(bar, #ccc);
CSS Output
body someElement {
color: #000000;
}
body .someClass {
color: #000000;
}
body.foo someElement {
color: #ffffff;
}
body.foo .someClass {
color: #ffffff;
}
body.bar someElement {
color: #cccccc;
}
body.bar .someClass {
color: #cccccc;
}
Obviously if there were many elements and a lot of color dependent things going on, this could get big fast. Imagine 100 elements under body with three color variations as above, and you have 300+ lines of CSS, 200+ (two-thirds) of which do not apply to any one page. And this doesn't account for other changes, like background colors, etc. In such a case, it is best to set up different LESS files that import a different set of values for #base and build different style sheets to be loaded on the pages that need it. However, if you are just doing a small subset of color changes to a page, this could be a valid way to go.
There is no way to do that.
LESS has no way to know whether the selector body.foo will apply at compile time.

Can I create Less color themes with variables that rely on other variables?

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’;

Resources