How may I pass a variable to :extend when using Less? - less

I would like to use a variable within a Less mixin that when passed to :extend has the same result as if I had instead used :extend with a class name string.
In the example below I have commented out a line that produces the CSS output I want by using :extend with a string.
But how can I do this with the #class-name variable instead?
.class-to-be-extended {display: block;}
.my-mixin (#class-name) {
#class-string: ~".#{class-name}";
.my-extra-class {
// &:extend(.class-to-be-extended); // works
&:extend(#{class-string}); // doesn't work, but no errors
}
}
.my-mixin(class-to-be-extended);
The CSS output I would like is:
.class-to-be-extended,
.my-extra-class {
display: block;
}
At the time of writing this I'm using the latest version I can find which is Less 1.4.2

This is not possible with Less version 1.4.2. (Thanks to Jon Schlinkert for letting me know via Twitter).
A feature request has been submitted to https://github.com/less/less.js/issues

Related

Why can't I put the { of an anonymous class at a new line in Kotlin?

This question may be stupid but... why? Personally I like the Microsoft style where { is at the same column as the matching }. In all languages I have used, it did not matter where { was placed.
But in Kotlin, only this works.
image_view.viewTreeObserver.addOnGlobalLayoutListener{
};
And this causes an error.
image_view.viewTreeObserver.addOnGlobalLayoutListener
{
};
https://kotlinlang.org/docs/reference/grammar.html#semicolons
Because your second example has the same meaning as
image_view.viewTreeObserver.addOnGlobalLayoutListener;
{
};
a property access followed by an empty lambda.
Braces in the same column and indented with the line above is not Microsoft style - it's known as the Allman style. It's a style I wish people would use, but sadly K&R's ancient style was pushed by Sun (Java) as the "official" style and Kotlin has followed suit.
You can do this:
image_view.viewTreeObserver.addOnGlobalLayoutListener()
{
}
to stop Kotlin complaining.
For further information on styles, see:
https://en.wikipedia.org/wiki/Indentation_style

how to generate css (like .E.F) using less.js compiler

I would like to generate CSS using less compiler..
Originally I have a less file and I need to prepend every rule with some class (not a nested selector)
.E{ .F{ color:blue; } }
is going to generate
.E .F{color:blue;}
In my case I don't want it to be nested but should get generated in the following way
.E.F{color:blue;}
.E {
&.F { color:blue; }
}

LESS: Change on-the-fly passed parameter through Mixin call

I have a LESS Mixin called in different stylesheets (i.e. one for each breakpoint controlled by media queries). In each stylesheet it is called with different parameter value such as:
"mobile.less":
.mixin(1);
"tablet.less":
.mixin(2);
.....
The mixin is defined (for example) as:
.mixin(#parameter) when (#parameter = 1)
{
body
{
font-style:italic;
}
.......
}
.mixin(#parameter) when (#parameter = 2)
{
.......
}
I'm developing a demo website so I wish that users could change this values on-the-fly changing value that is passed as parameter using a form field.
I tried the following method:
less.modifyVars({'#parameter' : <value from form field>});
But it would work only if #parameter is a "global" variable, not a passed parameter through the call...... Is there a method to change also passed parameters?
Thank you.
Original Answer
Yes, just make the variable outside the scope of the mixins but still use it in the guard expression. Something like:
#parameter: 1;
.mixin() when (#parameter = 1) {
body {
font-style:italic;
}
}
.mixin() when (#parameter = 2) {
body {
font-style:normal;
}
}
.mixin();
This generates the 1 code. If the variable gets set to 2, it generates the 2 code, etc.
Discussion of "re-process on the fly called mixins"
With reference to your comment, to my knowledge there is no way to directly re-process the local variable of a mixin call without doing something to the mixin definition itself to allow for it. So in your example, if "mobile.less" has a .mixin(1); call, how can you reprocess it to be, say, .mixin(4) based on user input. If you have not set up the call with a variable to begin with, then there is not way to "modify" the 1 in the original call. However, setting up with a variable call to begin with is really just a longer version of the answer I give above. Consider that this code essentially does the same as the above, only with more coding involved:
LESS Mixins Defined
.mixin(#parameter) when (#parameter = 1) {
body {
font-style:italic;
}
}
.mixin(#parameter) when (#parameter = 2) {
body {
font-style:normal;
}
}
Calls it in Files
//mobile.less
#parameter: 1;
.mixin(#parameter);
//tablet.less
#parameter: 2;
.mixin(#parameter);
Notice that we are still working with a "global" #parameter variable that is just being passed in as a "local" variable of the same name to the mixins. So all we gain here is more code (the addition of the local variable) to do the same thing.
Now assuming you are really after modifying the final output css behavior through the user input, then you may be able to "override" by a later call. This assumes that all the same properties, selectors are set by the various mixin calls, just to different values. So let us assume .mixin(1) is still in "mobile.less", you could set up a "reset.less" file that is called on user input to override by the css cascade.
LESS Mixin Definition Added
.mixin(#parameter) when (#parameter = 0) {
//purposefully empty, used as default for reset.less
}
Calls in your current "mobile.less" etc. remain as they are. You can have a global value of #parameter: 0; set in your global "variables.less" file, and then "reset.less" is this:
//reset.less
.mixin(#parameter);
That way "reset.less" outputs nothing by default (using the mixin definition just done above). This "reset.less" file is put last in the html processing so that it follows any "mobile.less" stylesheets, etc. Then, when the user changes #parameter, the "reset.less" is updated with the new values, and it does output css, which, by virtue of the css cascade, overrides the values of "mobile.less" etc.

On input of long escaped property value in LESS, how to split it to a newline

Suppose I have a really long escaped property value to input in LESS. I can get it to output with newlines in the final formatted css by setting a variable to add a newline like so #nl: `"\n"`; and use that in my escaped string to output newlines in the property value. So this:
#nl: `"\n"`;
.test {
property: ~"one,#{nl} two";
}
Will output this:
.test {
property: one,
two;
}
The question is whether there is any way to input it with newlines, something like:
.test {
property: ~"one,
two";
}
This throws a Parse error: Unrecognised input in LESS. A long set of property values like one might have with a progid:DXImageTransform.Microsoft.Matrix would benefit from being able to code it with newlines to begin with.
Though I posted an answer to my own question that I discovered worked, I'm open to a simpler one if it exists.
Well, one solution I have found is to put each line in its own escaped string. So this seems to work reasonably well for both input and output (depending on what the tab setting is):
Input LESS
#nl: `"\n\t\t\t"`;
.test {
property: ~"#{nl}"
~"one,#{nl}"
~"two";
}
Output CSS
.test {
property:
one,
two;
}
In short, no. Less does not support any kind of multiline strings (Recently this feature was proposed and rejected for various reasons). Though, speaking of IE hacks, the following code compiles fine since v1.4.2:
.rotate(#angle) {
#cos: cos(#angle);
#sin: sin(#angle);
#nsin: (0-sin(#angle));
-ms-filter: progid:DXImageTransform.Microsoft.Matrix(
M11=#cos,
M12=#sin,
M21=#nsin,
M22=#cos,
sizingMethod='auto expand'
);
}
test {
.rotate(20deg);
}
The only problem there is the combination of =, - and func() that needs some special handling.
Update,
as for the per line escaped strings example I guess the following would look a bit more clear:
#nl: ~`"\n "`;
.test {
property: #nl
~"one", #nl
~"two";
}

User defined functions with LessCSS?

I have just recently gotten into LessCSS and I am running into what I feel is major limitation and I was wondering if there was a way to do this?? I want to say I read somewhere that Sass allows for user defined functions but will LessCSS do the same?
What I'm wanting to do:
#fs: 16;
// either return the value
.s(#t,#s,#u) {
// return #t/#s*#u;
}
#elem {
margin-top: .s(30,#fs,1em);
width: .s(900,#fs,1em);
.child {
width: .s(100,900,100%);
}
}
// or have a property argument
.s(#t,#s,#u,#p) {
#{p}: #t/#s*#u;
}
#elem {
.s(30,#fs,1em,margin-top);
.s(900,#fs,1em,width);
.child {
.s(100,900,100%,width);
}
}
The only way I can figure it out, but it is very limited because I have to have multiple mixins:
.s(#t,#s,#u,#p) when (#p = margin-top) { margin-top: #t/#s*#u; }
// margin[-top|-right|-bottom|-left]
// padding[-top|-right|-bottom|-left]
.s(#t,#s,#u,#p) when (#p = width) { width: #t/#s*#u; }
.s(#t,#s,#u,#p) when (#p = height) { height: #t/#s*#u; }
I know I can always modify the less.js file to add a spacing function like the built-in round() or ceil() function. But, that kills the option of compiling the .less files for production using LessPHP, Crunch, SimpLess.
As far as I know, there's no property argument: you must write it down.
That is, a function will return a calculated value or instruction(s) (property/ies and calculated values).
There aren't thousands of properties in CSS, it's not a CMS with hundreds of classes and functions, so your list won't be as long as you can imagine. You should use other CSS preprocessors or a backend language to generate your CSS if you want to do such complicated things. Or better keep it simple.
That said, lessphp allows for user functions:
lessphp has a simple extension interface where you can implement user functions that will be exposed in LESS code during the compile. They can be a little tricky though because you need to work with the lessphp type system.
Notice that you also can easily add custom functions to the default Less compiler, which enable you to use the client side less.js compiler for testing and the command line lessc compiler for production.
For Less 1.x
Download and unzip the source from github at: https://github.com/less/less.js/releases/latest
Run npm install
Open the lib/functions.js file
Add your custom function (returncenter() in this example) inside the tree.functions object, for instance as follows:
tree.functions = {
returncenter: function() {
return new(tree.Anonymous)('center');
},
//original function below
}
Run grunt dist
After the preceding step you can include dist/less-1.x.x/js in your HTML or compile your Less code with the dist/lessc compiler.
For Less 2.x
Download and unzip the source from github at: https://github.com/less/less.js/archive/master.zip
Run npm install
Create a file caleld lib/less/functions/custom.js and write down the following content into it:
var Anonymous = require("../tree/anonymous"),
functionRegistry = require("./function-registry");
functionRegistry.addMultiple({
returncenter: function() {
return new(Anonymous)('center');
}
});
Open the lib/less/function/index.js file and append require("./custom"); to the list of register functions, just before return functions;
Run grunt dist
Now you can use the following Less code:
selector {
property: returncenter();
}
The preceding Less code will compile into the following CSS code:
selector {
property: center;
}