How to pass argument from mixin to another in lesscss? - less

I'm using the LESS CSS module 7.x-2.4 in Drupal 7.8
I would like to use style mixins which pass arguments to another mixin. In the example passing the color as a string "#CC00CC" works ok, but not as an variable like that "darken(#col, 10%)".
#bg(#colBg){
background-color: #colBg;
}
#style(#col){
border: 2px solid lighten(#col, 10%); // ok
#bg(#CC00CC); // ok - color is passed
#bg(darken(#col, 10%)); // Color is not being passed to #bg
}
.buttonSubmit{
#style(#FF00FF);
}
How can I achieve cascading variables from the css-class to a mixnin which passes the argument to another mixin?

Your syntax is incorrect. Check the docs on mixins. The code you have should be written like this:
.bg(#colBg){
background-color: #colBg;
}
.style(#col){
border: 2px solid lighten(#col, 10%);
.bg(#CC00CC);
.bg(darken(#col, 10%));
}
.buttonSubmit{
.style(#FF00FF);
}

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.

2 Less Parameter with one being null by default

Hey I have 2 sets of icon styles. Black and White
settings-icon-white.png or settings-icon.png
Now I am using a Less mixin which takes a text parameter:
//The mixin
.icon-finder(#url){
background-image: url("../images/icons/backend/#{url}-icon.png");
background-size: cover;
}
//generated class:login-icon.png
.icon-login{
.icon-finder(login);
}
Now the challenge is that I want to also have an option to select a white icon if the parameter gets passed a white. Is there a way to have a default null parameter, but can be used if need be?
So for example:
.icon-finder(#url,#white){
background-image: url("../images/icons/backend/#{url}-icon#{white}.png");
background-position: center center;
}
But I don't want white the whole time, so can this be null? #white = "" I did see this #_ being used before - is that right?
So the code would be like:
.icon-admin{
.icon-finder(admin);
}
.icon-admin-white{
.icon-finder(admin,white);
}
Am I missing something? Thanks in advance!
Yes, you can set a default value to a mixin argument by just specifying it in the mixin declaration like in the below code block. The #white: '' part means that the mixin will take the value for #white as an empty string when no value is provided in the call.
.icon-finder(#url,#white: ''){
background-image: url("../images/icons/backend/#{url}-icon#{white}.png");
background-position: center center;
}
.icon-admin{
.icon-finder(admin);
}
.icon-admin-white{
.icon-finder(admin,white);
}
There is no need to use the #_ syntax that is mentioned in the link.
Note that if you are writing something like a mixin library and want to restrict the values for the second parameter to white or nothing (the above mixin allows you to send any value for second param), then you could use one of the following options also:
Option 1: Two separate mixins, one with a hard-coded white value (note that it is not a variable) and another with only one parameter. This way if the user tries to pass any other value it will be rejected.
.icon-finder(#url,white) {
background-image: url("../images/icons/backend/#{url}-iconwhite.png");
background-position: center center;
}
.icon-finder(#url){
background-image: url("../images/icons/backend/#{url}-icon.png");
background-position: center center;
}
.icon-admin{
.icon-finder(admin);
}
.icon-admin-white{
.icon-finder(admin,white);
}
Option 2: Using guards and checking if the value is white or not. If it is then use the white background image, else use the default.
.icon-finder(#url,#white: '') {
& when (#white = white){
background-image: url("../images/icons/backend/#{url}-iconwhite.png");
background-position: center center;
}
& when not (#white = white){
background-image: url("../images/icons/backend/#{url}-icon.png");
background-position: center center;
}
}
.icon-admin{
.icon-finder(admin);
}
.icon-admin-white{
.icon-finder(admin,white);
}
The advantage of the first option is that if any value other than white is given, the compiler would throw an error and alert the user that a wrong value is provided whereas the second one will silently switch to the default.

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...

Making a SCSS mixin with an optional argument that is passed to the property name

I have been reading through a couple of answers but none of these help me where I need it.
I want to write a rule for borders that consist of three variables. The first is optional and makes clear which side the border should be on (top, right, bottom or left; if not present the default should simply be border:). The second one defines the width of the border and the latter the colour. I tried something like this. But that doesn't work unfortunately, because I don't provide a third argument I am guessing.
#mixin border($direction,$size,$colour) {
#if variable-exists($direction) {
border-#{$direction}: $size solid $colour;
} #else {
border: $size solid $colour;
}
}
$borderradius: 2px;
$borderSize: 1px;
$mainColour: #ccc;
$hoverColour: #4679bd;
#include border($borderSize, $mainColour);
You could try this solution. By adding the optional variable at the end of your arguments. Keep in mind that you have to place the optional variable last in your arguments order.
#mixin border($size, $colour, $direction:"") {
#if $direction != "" {
border-#{$direction}: $size solid $colour;
}
#else {
border: $size solid $colour;
}
}
$borderradius: 2px;
$borderSize: 1px;
$mainColour: #ccc;
$hoverColour: #4679bd;
div {
#include border($borderSize, $mainColour);
}
An example: http://sassmeister.com/gist/560cb13c92498d6d39e6

Is there a way to add a mixin into a variable in LESS

Can I add a mixin to a variable in LESS?
Something like this
#input-border-radius: .rounded();
or
#h1: .font-size(46) // This pulls from the rem calculator mixin.
Looked at the LESS Docs but can't see a way to do it.
There is a way.
You can define properties of a (possibly immaginary) class and recall the properties of that class in the style of a different class. For example:
.fontstyling {
font-weight: bold;
color: black;
}
h1 {
font-size: 46px;
.fontstyling;
}
h2 {
font-size: 38px;
.fontstyling;
}
(thats not the best way to format the headings - but for other exemples it is really useful!)