I am trying to create a Less mixin for vendor properties that allows somebody to specify what CSS property they want to use, the value of the property, and what vendor(s) they want it for (Opera, Mozilla, Firefox, Webkit, IE, none).
I originally wrote the code in SASS here but am having a hard time porting it to Less.
Here is what I currently have:
.vendor(@property, @value, @vendors...) {
.vendor-detect() when (@vendors = webkit) {
-webkit-@{property}: @value;
}
.vendor-detect() when (@vendors = moz) {
-moz-@{property}: @value;
}
.vendor-detect() when (@vendors = ms) {
-ms-@{property}: @value;
}
.vendor-detect() when (@vendors = o) {
-o-@{property}: @value;
}
.vendor-detect() when (@vendors = official) {
@{property}: @value;
}
.vendor-detect();
}
Right now, the when you use the code as such:
.button {
.vendor(border-radius, 4px, official);
}
You get:
.button {
border-radius: 4px;
}
But I want to be able to declare multiple vendors with the mixin, so using:
.button {
.vendor(border-radius, 4px, webkit moz official);
}
Should provide me with:
.button {
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
But right now it doesn't.
So how do I go about looping through the vendors
parameter in this mixin, or can I even do that in Less?
You can loop through the vendors
parameter using the below method. The code is pretty straight forward to understand but I have added some inline comments to make it easier.
LESS:
.vendor(@property, @value, @vendors...) {
.loop-vendors(@vendorCount) when (@vendorCount > 0){ // for loop for creating the req prefixes
.loop-vendors(@vendorCount - 1); // call the next iteration
@vendor: extract(@vendors, @vendorCount); //extract the value from vendors list based on loop index
-@{vendor}-@{property}: @value; // populate the vendor specific versions.
}
.loop-vendors(length(@vendors)); // call the loop based on length of vendors list
@{property}: @value; //populate the official value finally
}
.button {
.vendor(border-radius, 4px, webkit moz ms o); // calling the vendor mixin
.vendor(box-shadow, 1px 1px 4px gray, webkit moz ms o); // calling the vendor mixin
}
Compiled Output:
.button {
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
-webkit-box-shadow: 1px 1px 4px #000000;
-moz-box-shadow: 1px 1px 4px #000000;
-ms-box-shadow: 1px 1px 4px #000000;
-o-box-shadow: 1px 1px 4px #000000;
box-shadow: 1px 1px 4px #000000;
}
Additional Info:
seven-phases-max has created a wrapper mixin for mimicking a for loop in LESS and a sample on that can be found in this thread. It is a very simple yet effective one and I recommend you to have a look at it. I have not used that in the sample code above because I wanted to show the most basic way of doing a loop. In the comments, he has also kindly contributed this gist which makes use of the for
wrapper.
This is another generic way to add vendor prefixes in LESS but it doesn't handle selectively based on the list of vendor prefixes required.
In the above sample, the official
keyword is not required in the vendors
list because it is auto-populated. It is a good practice to always leave it there to be future proof.