Conditional when in less-file - less

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.

Related

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

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

LESSCSS: interpolation of a mixin argument

I have the following code:
#red_SOPRA: orange;
#red: red;
.gradient(#color) when (#color = red)
{
background: linear-gradient( 180deg, #color 0%,yellow 100%);
}
div
{
.gradient(red);
}
Compiled into:
div {
background: linear-gradient(180deg, #ff0000 0%, #ffff00 100%);
}
I would like to add "_SOPRA" to the end of variable "#color" present in background definition, in order to obtain an interpolated and dynamic name of variable used in mixin.
I tried with ## and #{color} definitions but without success.
How to obtain a generated background like this (with value "#ffa500" - #red_SOPRA value - instead of "#ff0000")?
div {
background: linear-gradient(180deg, #ffa500 0%, #ffff00 100%);
}
Option #1
Unless I'm missing something from what you are trying to achieve, then simply removing the guard expression when (#color = red) will get a "dynamic" value output for #color, allowing it to be called directly by #red_SOPRA or #blu_SOPRA (whatever you pass).
LESS
#red_SOPRA: orange;
#red: red;
.gradient(#color)
{
background: linear-gradient( 180deg, #color 0%, yellow 100%);
}
div {
.gradient(#red_SOPRA);
}
CSS Output
As you wanted...
div {
background: linear-gradient(180deg, #ffa500 0%, #ffff00 100%);
}
Option 2
You can set up the mixin to perform a "'merging' between string passed" and the "_SOPRA" suffix, something like this:
LESS
#red_SOPRA: orange;
#blu_SOPRA: blue;
.gradient(#pre; #SOPRA: ~'#{pre}_SOPRA'; #color: ##SOPRA)
{
background: linear-gradient( 180deg, #color 0%,yellow 100%);
}
div
{
.gradient('red');
}
.test {
.gradient('blu');
}
CSS Output
div {
background: linear-gradient(180deg, #ffa500 0%, #ffff00 100%);
}
.test {
background: linear-gradient(180deg, #0000ff 0%, #ffff00 100%);
}
This will not fail gracefully if #color does not resolve to a valid ##SOPRA value.
First of all, I would like to thank ScottS for his answer, especially second option that is what I needed.
Secondly, I add solution that finally yesterday I found by myself, very similar in philosophy but little different and (maybe) easier to understand by newby, due to a temp variable.
#red_SOPRA: orange;
#red: red;
.gradient(#color) when (#color = 'red')
{
#stop-1:~"#{color}_SOPRA";
background: linear-gradient( 180deg, ##stop-1 0%,yellow 100%);
}
div
{
.gradient('red');
}
Philosophy is the same, but with this "double passage" I think that could be more "talking"... :-)
UPDATE:
After correct comment of seven-phases-max, I updaded my solution. Please note that parameter must be passed as string with 'red'

How to pass argument from mixin to another in lesscss?

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);
}