Generic `vendors` mixin - less

Defining vendors' mixins is common task under LESS, ie:
.box-shadow() {
-moz-box-shadow:#arguments;
-webkit-box-shadow:#arguments;
-o-box-shadow:#arguments;
-ms-box-shadow:#arguments;
box-shadow:#arguments;
}
.border-radius() {
-moz-border-radius:#arguments;
-webkit-border-radius:#arguments;
-o-border-radius:#arguments;
-ms-border-radius:#arguments;
border-radius:#arguments;
}
...
But it seems a bit repeating...
What I would like is a generic vendor mixin which do this for me, ie:
.vendors(#prop, #val) {
-moz-#prop:#val;
-webkit-#prop:#val;
-o-#prop:#val;
-ms-#prop:#val;
#prop:#val;
}
Then defining box-shadow mixin would as simple as:
.box-shadow() {
.vendors(box-shadow, #arguments);
}
The problem is my .vendors mixin does not compile...
I tried:
.vendors(#prop, #val) {
-moz-#prop: #val; /* Error */
~"-moz-#{prop}": #val; /* Error */
~`"-moz-#{prop}": #val; /* Error */
}
Do you have an idea on how to do this?
Cheers

Stylus has this, which is called Interpolation, eg:
vendor(prop, args)
-webkit-{prop} args
-moz-{prop} args
{prop} args
border-radius()
vendor('border-radius', arguments)
box-shadow()
vendor('box-shadow', arguments)
— Then,
button
border-radius 1px 2px / 3px 4px
yields to:
button {
-webkit-border-radius: 1px 2px / 3px 4px;
-moz-border-radius: 1px 2px / 3px 4px;
border-radius: 1px 2px / 3px 4px;
}
\o/

Another option, that I think is a little cleaner, would be do create a list of vendors and then iterate over that list to create the particular styles you want. Here's an example:
ALLVENDORS = webkit moz o ms w3c
vendors(prop, args)
for vendor in ALLVENDORS
if vendor == w3c
{prop}: args
else
-{vendor}-{prop}: args
This creates a list of vendors that you want to support and then allows you to reuse them. if later, you decide you want to support another prefix or want to remove one, all you have to do is remove it from the list.
And then you would use the list just as shown above:
border-radius()
vendors(border-radius, arguments)
box-shadow()
vendor(box-shadow, arguments)

I'm pretty sure less now has it. I've used this code in a Meteor.js project:
.vendor(#property, #value) {
-webkit-#{property}: #value;
-khtml-#{property}: #value;
-moz-#{property}: #value;
-ms-#{property}: #value;
-o-#{property}: #value;
#{property}: #value;
}
.vertical-align {
position: relative;
top: 50%;
.vendor(transformY, -25%);
}

Related

Conditional when in less-file

I am making a theme editor for WordPress, and would like to use less to build the CSS file.
I have put a string in a variable like this:
#banner-separation-style: 'thick_border';
Then I'm trying to use when() like this:
when (#banner-separation-style = 'thick_border') {
header {
... some style
}
... and some css selectors
}
I've also tried combinations without quoting the variable.
How do I properly create something similar to if-blocks with less?
Guards (when statement) can only be used along with a mixin or a CSS selector. We can't write a when statement without using one of those. So, either write it with a mixin like below:
#banner-separation-style: 'thick_border';
.border-styles() when (#banner-separation-style = 'thick_border') {
header { border: 2px solid red; }
nav { border: 2px solid green; }
}
.border-styles;
or directly with the CSS selector like below:
#banner-separation-style: 'thick_border';
header when (#banner-separation-style = 'thick_border') {
border: 2px solid red;
}
nav when (#banner-separation-style = 'thick_border') {
border: 2px solid green;
}
or atleast using an unnamed selector (&) like below:
#banner-separation-style: 'thick_border';
& when (#banner-separation-style = 'thick_border') {
header { border: 2px solid red; }
nav { border: 2px solid green; }
}
The first version (with mixin) is the one that I prefer because (a) you don't have to repeat the condition multiple times like in the CSS selector version and (b) giving the mixin a name makes it more readable than using an unnamed selector. It is just my choice and some other user could actually prefer the last because it doesn't need that extra mixin call statement.

LESS dynamically create variable names from mixin

Hi I'm thinking if is possible to automate the process of creation variable names in less?
eg. At the moment I have to write:
#list-description-font-color: #000;
#list-description-border-color: #aaa;
#list-description-background-color: #bbb;
#list-description-border-width: #ccc;
Will be better if I could define in one place #list-description and than re-use. eg.
.list-description(#pre: 'list-description') {
#pre-font-color: #000;
#pre-border-color: #aaa;
#pre-background-color: #bbb;
#pre-border-width: #ccc;
}
Even better if I could have an array off extensions eg.
#ext: fc font-color, bc border-color, bgc background-color, bw border-width;
.list-desc(#pre: 'list-description') {
#pre-#ext{fc}: #000;
#pre-#ext{bc}: #aaa;
#pre-#ext{bgc}: #bbb;
#pre-#ext{bw}: #ccc;
}
And this will generate the original output.
Thanks

Is it possible to manipulate css variables using LESS?

With preprocessor variables it's easy to set up one variable and manipulate it so that I can use it to set multiple properties. (demo)
While experimenting with native css variables, I noticed that I could combine them with preprocessor variables, so in the following example: (use firefox)
h1 {
--length: 40px;
#length: var(--length);
line-height: #length;
border: 5px solid tomato;
}
line-height was correctly rendered at 40px
But, when I tried to manipulate the preprocessor variable - like this:
h1 {
--length: 40px;
#length: var(--length);
#length2: #length*2;
line-height: #length;
padding: #length2;
border: 5px solid tomato;
}
... the code failed.
Is this possible somehow?
As mentioned in my comment, my understanding of CSS variables is that the variable is resolved into its actual value by the UA. This happens after the Less compiler compiles the file and thus it wouldn't be aware of what is the actual value contained by the CSS variable.
To the compiler, the value of #length is only var(--length). Since this is not a number, an error is thrown during compilation indicating that the math operation is being done on an invalid type.
OperationError: Operation on an invalid type on line 4, column 3:
One way to fix this would be to make the Less compiler output the variable name as it is and have the multiplier appended to it (like string concatenation). This would then leave the control to the UA.
But since all CSS math operations have to be given within calc() function, the entire thing has to be wrapped within it. So, the below code would work fine.
h1 {
--length: 40px;
#length: var(--length);
#length2: ~"calc(#{length} * 2)";
line-height: #length;
padding: #length2;
border: 5px solid tomato;
}
Or, even the below would be enough if --strict-math is enabled during compilation:
h1 {
--length: 40px;
#length: var(--length);
#length2: calc(#length * 2);
line-height: #length;
padding: #length2;
border: 5px solid tomato;
}
Above code when compiled produces an output similar to the one in Example 11 of the specs and so it should be a reasonably good way of doing this :)
... Note, though, that calc() can be used to validly achieve the same thing, like so:
.foo {
--gap: 20;
margin-top: calc(var(--gap) * 1px);
}
var() functions are substituted at computed-value time...

How to Add in Less Meta Informations for a Mixin Class? (phpStorm)

Is it possible in Less to setup mixin informations that can read phpStorm?
I write a Mixin like this:
.action-btn(#size: 32px, #color: #fff, #bgColor: #overlayStyleBlack, #bgColorHover: #red) {
a {
width: #size;
display: block;
color: #color;
text-align: center;
line-height: #size;
background-color: #bgColor;
&:hover {
cursor: pointer;
background-color: #bgColorHover;
}
}
}
What i want now is, that when i use this mixin in another less file: ".action-btn();" then i want to see that i have in this Mixin 4 Settings that i can Setup. In php Classes i can do this with:
/**
* #param string $xxx
* function to check and change user is_online flag in sphinx and in mysql
*/
But this dont work in the Less Mixin File.
And how can i Skip some settings? Here a example to explain what i mean. (This ry dont worked)
.action-btn(64px, , , #fff);

How to mix in generated sprites mixins to loop-generated classes in LESS?

I'd like to generate multiple classes with mixed in sprites, using recursive, guarded mixins (and LESS compiler version 1.7).
The basic idea looks like this:
.sprite-img {
background: url("sprite.png") no-repeat;
}
.icon_1 { width: 26px; height: 23px; background-position: -27px -27px; }
.icon_1_hover { width: 26px; height: 23px; background-position: -73px -51px; }
.icon_2 { width: 26px; height: 22px; background-position: -73px -28px; }
.icon_2_hover { width: 26px; height: 22px; background-position: 0 -48px; }
// setup some lists
#colors: #efa, #a77 ...;
#IDs: 1, 10,...;
.generate-colored-toggles(#n, #i: 1) when ( #i =< #n) {
#c: extract(#colors, #i); // subtracts 1 from index for list access
#j: extract(#IDs, #i);
.container .toggle._#{j} .img-holder {
border-color: #c;
.sprite;
/* LESS compiler error: */
.icon_#{i}; // adding parentheses won't work either
&:hover {
.icon_#{i}_hover;
}
}
.generate-colored-toggles(#n, (#i + 1)); // recurse
}
.generate-colored-toggles(length(#colors));
The resulting classes ( ._1 ... ._n ) are to be assigned, dynamically (in a loop, cf. JSF's ui-repeat), during page generation.
Now I'm facing numerous limitations:
My sprites are generated using http://zerosprites.com/; thus, names of the sprite mixin classes .icon_ are taken from the image file names, and should therefore not be modified.
The .toggle's structure is determined by my widget library and should be left unchanged. This prevents me from assigning the specific sprite image class to the .img-holder directly in the markup.
Can you think of a workaround (preferably, using LESS only)?