Strange operations behaviour with LESS - less

This one compiles:
.myclass {
.mymixin(2);
}
.mymixin(#parameter) {
width: ((#parameter*1)*12px);
}
This one does not:
.myclass {
.mymixin(2);
}
.mymixin(#parameter) {
width: ((#parameter-1)*12px);
}
Does anyone have a clue what's the problem with the second one?

Less treats #parameter-1 as a variable as you can tell from the compiler error:
Error line 2: variable #parameter-1 is undefined
If you insert spaces it works as expected:
.mymixin(#parameter) {
width: ((#parameter - 1)*12px);
}

Related

LESS variable name for mixin with parameters

What I want:
a mixin with parameters named by a variable.
Without parameters it works like a charm:
#foo: test;
.#{foo} {
length: 20px;
}
.bar {
.test;
}
puts out:
.bar {
length: 20px;
}
Perfetct so far.
Now I want to do this:
#foo: test;
.#{foo}(#var) {
length: #var;
}
.bar {
.test(20px);
}
unfortunately outputs ..
ParseError: Missing closing ')' on line 3, column 9:
2
3 .#{foo}(#var) {
4 length: #var;
I've already tried all crazy sorts of escaping. No luck so far.
Any ideas?

Apply class to all instances of parent selector in LESS

I've got this LESS stylesheet. The idea it to alias a lot of icon classes to my local classnames in our "namespace".
// base-icons.less
.base-icon {
display: block;
font: "myFont.otf"
}
.base-icon-foo { content: 'foo' }
.base-icon-bar { content: 'bar' }
.base-icon-fiz { content: 'fiz' }
// my-icons.less
.my-icon {
&-foo { .base-icon; .base-icon-foo; }
&-bar { .base-icon; .base-icon-bar; }
&-fiz { .base-icon; .base-icon-fiz; }
}
Is there a way to prevent having to add the .base-icon class to each single line in the my-icons.less file? I want to apply the css to all classes that start with .my-icon but it would be cleaner to not have to type the .base-icon class each time.
Learn mixins and extend. E.g. (assuming you can't modify base-icons.less):
// base-icons.less
.base-icon {
display: block;
font: "myFont.otf"
}
// my-icons.less
.i(foo);
.i(bar);
.i(baz);
.i(#name) {
.my-icon-#{name} {
&:extend(.base-icon);
content: '#{name}';
}
}
Also see stuff like In LESS, can I loop over class/mixin "patterns"?

Less mixin calling another mixin won't generate nested rules

I have a Less project set up with three files relevant to my question.
A config file which just holds variables and their values.
A controller file which my Less watcher is told to compile.
A mixin file, titled _buttons.less, which I import as a reference in the
controller file.
Inside the controller file, I have a rule:
.bananas {
.nesting-mixin(#color-list);
}
Inside the variable file, I have a list:
#color-list : red, blue, green, black;
Inside the mixin file, I have two mixins:
.do-the-mixin(#list) {
color: extract(#list, 1);
&.blue {
color: extract(#list, 2);
}
&.green {
color: extract(#list, 3);
}
}
.nesting-mixin(#list) {
&.colored {
.do-the-mixin(#list);
}
}
When I call the .nesting-mixin method from the controller file, the output is:
.bananas.colored {
color: #ff0000;
}
But when I move the nesting mixin into the controller file, I get:
.bananas.colored {
color: #ff0000;
}
.bananas.colored {
color: #ff0000;
}
.bananas.colored.blue {
color: #0000ff;
}
.bananas.colored.green {
color: #008000;
}
Is there some aspect of Less mixin importing or nesting that I don't understand? The second output is what I want, but I don't understand why it needs to be in the same file from which it's called.
Thanks for reading. :)

LESS: Guarded Mixins like MediaQuery

I would like to use LESS Guarded Mixins in a way similar to MediaQuery concept, so declaring a condition that, if verified, contains a set of css rules and declaration.
For the moment I wrote this example code:
.color-theme(#color-type) when (#color-type='cold')
{
color:gren;
}
.color-theme(#color-type) when (#color-type='hot')
{
color:red;
}
text-container
{
.color-theme('hot');
width:960px;
}
My intention is to write a set of classes that must be used only if a particular condition is satisfied, in a way very similar to MediaQueries logic.
This lines of code runs... but in this wa I should repeat the parameter value 'hot' for each new css class.
I would like to have something like
when (#color-type='hot')
{
body { ... }
.myclass { ... }
...
}
How could I obtain this?
This is not really possible exactly like that (as you can not pass a block into a mixin you are calling ... what you are trying to do is possible in Sass with the #content directive). What you could do in Less instead, is define a mixin that outputs a particular block (cold or hot) depending on the #color-type variable passed.
a) Mixins with specific arguments:
First you can make a general output mixin, that does not show anything, no
matter what the #color-type is (so you don't get an error if an undefined block is called):
.show(#color-type) { }
Then you define the blocks (similarly to how you would do with media
queries, except here you will need an extra mixin call):
.show('cold') {
body {
color: blu;
}
.myclass {
background: url(cold.png);
}
}
.show('hot') {
body {
color: red;
}
.myclass {
background: url(hot.png);
}
}
Now you just need to call the mixin. And depending on what the variable you pass, the right block will be
shown (or if no block with that variable has been defined, there
will be no output). For example now you can call show(), passing a
variable that you defined somewhere earlier:
#color-type: 'hot';
.show(#color-type);
or directly
.show('hot');
and the CSS output will be:
body {
color: red;
}
.myclass {
background: url(hot.png);
}
b) Guards:
Instead of defining the mixins with particlular arguments (e.g. .show('hot'){ ... }), you can use guards, like so: .show(#color-type) when (#color-type = 'hot') { ... }), or alternatively like so: .show() when (#color-type = 'hot') { ... } if you define the variable somewhere earlier and the just have to call the mixin .show() to return the respective block:
.show() when (#color-type = 'cold') {
body {
color: blue;
}
.myclass {
background: url(cold.png);
}
}
.show() when (#color-type = 'hot') {
body {
color: red;
}
.myclass {
background: url(hot.png);
}
}
// setting the variable
#color-type: 'hot';
// calling the mixin
.show();
Maybe also of interest - some discussion connected to this topic:
Issue #965: Mixins should accept LESS blocks

LESS Preprocessing and null arguments?

This might be difficult to explain. Is there a way to have less not write out the #child argument without overloading the mix-in? I really don't want two mix-ins. If I use "" double quotes are outputted. I would like the LESS compiler to leave it blank.
LESS CODE
.build-on(size, #child)
{
&--1-1 #{child}
{
width: 100%;
}
&--1-2 #{child}
{
width: 50.0%;
}
&--1-3 #{child}
{
width: 33.3%;
}
&--1-4 #{child}
{
width: 25.0%;
}
&--1-5 #{child}
{
width: 20.0%;
}
}
// I might need to provide a child element
.data-table
{
.build-on(size, table);
}
// I might not
.grid
{
.build-on(size, "");
}
Pass it like so:
.yourClass
{
.build-on(size, ~'');
}
Or Better Yet...
Define a default: .build-on(size, #child: ~'') { ... } then no second is needed:
.yourClass
{
.build-on(size);
}