Less colors in rgba() even if alpha channel is 1 - less

I need that Less compiler don't convert to HEX colors defined in rgba(), even if alpha channel is 1
Actually, the following Less code:
#color1: rgba(0,0,0,1);
#color2: rgba(0,0,0,0.1);
#color1_light: lighten(#color1,90%);
#color2_light: lighten(#color2,90%);
.a {
background:#color1;
color: #color1_light;
}
.b {
background:#color2;
color: #color2_light;
}
is processed to:
.a {
background: #000000;
color: #e6e6e6;
}
.b {
background: rgba(0, 0, 0, 0.1);
color: rgba(230, 230, 230, 0.1);
}
but I need to have (for many reasons related to further evaluations)
.a {
background: rgba(0, 0, 0, 1);
color: rgba(230, 230, 230, 1);
}
.b {
background: rgba(0, 0, 0, 0.1);
color: rgba(230, 230, 230, 0.1);
}
How to solve this?

Basically this is pretty easy, all you have to do is to escape your expression, below you will find two examples how to force less compiler to display rgba format even though alpha is 1:
#color1: rgba(0,0,0,1);
body {
color: ~"rgba("red(#color1), green(#color1), blue(#color1),~" 1)";
background: %(~"rgba(%s, %s, %s, 1)", red(#color1), green(#color1), blue(#color1));
}
Both examples will produce rgba(0, 0, 0, 1), it's up to you which one do you prefer. I bet you will find more info in the docs under string escape and string replace
//EDIT
yup, this is tricky, but still, you can extend this with a mixin so it won't look that bad in code hereafter.
#color1: rgba(0,0,0,1);
.rgba(#color) {
//#rgba: ~"rgba("red(#color), green(#color), blue(#color),~" 1)";
#rgba: %(~"rgba(%s, %s, %s, %s)", red(#color), green(#color), blue(#color), alpha(#color));
}
.torgba(#property, #color) {
#{property}: %(~"rgba(%s, %s, %s, %s)", red(#color1), green(#color1), blue(#color1), alpha(#color1));
}
body {
.rgba(#color1); // mixin returns #rgba variable that may be used later on, it's not color object however, but a string
color: #rgba;
background: #rgba;
.torgba(border-color, #color1); // do the same, but returns property with color in given format
}

Related

Passing a variable list through .for loop using Less 2.6.1 is unable to compile

I have been using a Less mixin which makes looping in Less, less verbose and is really handy: https://github.com/seven-phases-max/less.curious/
I upgraded from Less 2.6.0 to Less 2.6.1 and now the Less will not compile.
Here's the Less code:
// ............................................................
// .for
.for(#i, #n) {.-each(#i)}
.for(#n) when (isnumber(#n)) {.for(1, #n)}
.for(#i, #n) when not (#i = #n) {
.for((#i + (#n - #i) / abs(#n - #i)), #n);
}
// ............................................................
// .for-each
.for(#array) when (default()) {.for-impl_(length(#array))}
.for-impl_(#i) when (#i > 1) {.for-impl_((#i - 1))}
.for-impl_(#i) when (#i > 0) {.-each(extract(#array, #i))}
#gray-base: #000;
#gray-darker: #222;
#gray-dark: #333;
#gray: #555;
#gray-light: #777;
#gray-lighter: #eee;
#gray-type:
gray,
gray-base,
gray-dark,
gray-darker,
gray-light,
gray-lighter;
.gray-type {
// Mixin to generate the gray font colours for p tags in the font stacks.
.for(#gray-type); .-each(#name) {
.#{name} {
color: ##name;
}
}
}
Here's the expected output:
.gray-type .gray {
color: #555;
}
.gray-type .gray-base {
color: #000;
}
.gray-type .gray-dark {
color: #333;
}
.gray-type .gray-darker {
color: #222;
}
.gray-type .gray-light {
color: #777;
}
.gray-type .gray-lighter {
color: #eee;
}
After upgrading to Less 2.6.1 I get the following error:
>> SyntaxError: variable #[object Object],[object Object] is undefined in less/style.less on line 41, column 3:
>> 40 // Mixin to generate the gray font colours for p tags in the font stacks.
>> 41 .for(#gray-type); .-each(#name) {
>> 42 .#{name} {
Warning: Error compiling less/style.less Use --force to continue.
I think the problem is related to the hyphens being stripped from the variables during compilation, therefore making the variables passed though the list invalid.
Any help would be greatly appreciated.

Less CSS, please explain Advanced arguments and the #rest variable to me?

Simple question: I don't understand what the Advanced arguments do in Less CSS, as per http://lesscss.org/features/#mixins-parametric-feature-advanced-arguments-and-the-rest-variable . I've battled to get my head around how it's explained there.
I understand this:
.mixin(#a: 1) {
But I don't understand the following two, where the ... is introduced:
.mixin(...) { // matches 0-N arguments
.mixin() { // matches exactly 0 arguments
.mixin(#a: 1) { // matches 0-1 arguments
.mixin(#a: 1; ...) { // matches 0-N arguments
.mixin(#a; ...) { // matches 1-N arguments
.mixin(#a; #rest...) { // #rest is bound to arguments after #a
// #arguments is bound to all arguments }
I'm learning Less because I'm very keen on bootstrap, but this puzzled me.
Thank you very much!
Well, okay you should also read http://lesscss.org/features/#mixins-parametric-feature-pattern-matching.
In Less only mixin that match the number of arguments of the caller are compiled. Notice also that when two or more mixins match, all of them are compiled into CSS.
When you mixin got one argument, like that shown below:
.mixin(#a) {}
Only callers with one argument match and will be compiled: .mixin(3); or .mixin(1) and so on. But NOT .mixin() or .mixin(1,2,3)
When you set a default value for the first argument, for instance 3, as shown below:
.mixin(#a: 3) {}
Now not only calls with 1 argument match, but also calls with zero arguments:
.mixin(#a: 3) {property: #a;}
p{ .mixin();}
outputs:
p {
property: 3;
}
Now take a look to the special ... argument, that argument matches any number of arguments. So .mixin(...) will match and get compiled the following callers .mixin(), .mixin(1) and .mixin(1,2,3,4).
When you prepend a name (including the #) to the ... argument the values will be assigned to a variable with that name:
.mixin(#listofvariables...) {
p: #listofvariables;
}
p {
.mixin(one; two; three);
}
outputs:
p {
p: one two three;
}
Notice that ... assigns the arguments to a list, which can be manipulated with the list functions too.
An mixin such as .mixin(#a; ...) is a variant of the preceding two use cases. This mixins requires a first argument set, followed by zero or any other arguments.
#arguments is a special variable that contains a list of all argument of the mixin:
.mixin(#a; #b) {p1: #arguments; p2:extract(#arguments,2); p3:#b;}
p {.mixin(1; 2);}
outputs:
p {
p1: 1 2;
p2: 2;
p3: 2;
}
So the #arguments variable can be used in any mixin and does not require an ... argument.
What would a caller for a mixin like this look like? .mixin(#a; ...)
could it be something like this: .mixin(#a,53px); ? How does it
determine where the 53px goes to?
The 53px is not assigned to a variable, but it is the second item of the #arguments list. You can get it by extract(#arguments,2).
An use case for the .mixin(#a; ...) {} can be to assign a property always when .mixin() regardless the number of arguments, example:
.mixin(#a; ...) { color: #a;}
.mixin(#a) { background-color: contrast(#a); width:100%;}
.mixin(#a; #b;) { background-color: contrast(#a); width:#b;}
div {
.mixin(red);
}
div.small {
.mixin(red,50%);
}
outputs:
div {
color: red;
background-color: #ffffff;
width: 100%;
}
div.small {
color: red;
background-color: #ffffff;
width: 50%;
}
notice that the .mixin(#a; #rest...) {} assigns 35px the first item of the #rest list. And so the following Less code:
.mixin(#color,#padding...) {
color: #color;
padding: #padding
}
div {
.mixin(red; 10px; 20px; 5px; 5px);
}
outputs:
div {
color: red;
padding: 10px 20px 5px 5px;
}

Smart margin mixin for LESS

I've created a .smartMargin() mixin for LESS CSS to be used in responsive design LESS.
I'm sharing it here for the benefit of others and also because I'm curious if there's any way to make it more efficient.
Idea
The mixin is designed to be called from within another mixin that represents a responsive design breakpoint. The idea is that you may want to override top, left, bottom, right margins individually by overriding one or more margins in each successive breakpoint.
In main mixin I just want one parameter for #videoMargin as opposed to #videoMarginLeft, #videoMarginRight etc so that's why I've called it 'smartMargin'.
Usage
In my main file I define a breakpoint like this, and then call this mixin several times:
.breakpoint(#width, #color, #labelsSize, #videoMargin)
{
video
{
.smartMargin(#videoMargin);
}
}
.breakPoint(10em, red, 3em, 1em auto 1em auto);
.breakPoint(10em, green, 3em, 2em unset unset unset);
.breakPoint(20em, blue, 3em, unset 3em unset unset);
Output css
So for a given value of #videoMargin here's the output css generated
generated css
-------------
.smartMargin(3em); margin: 3em;
.smartMargin(3em 1em 2em 4em); margin: 3em 1em 2em 4em;
.smartMargin(3em unset unset unset); margin-top: 3em;
.smartMargin(3em unset unset 4em); margin-top: 3em;
margin-right: 3em;
Implementation
The mixin is as follows. It works well but it just seems a little clumsy in places and you need to provide either 4 or 1 parameters. If anybody can optimize this I'd be very interested to see.
.smartMargin(#margin) when (length(#margin) = 4)
{
._smartMargin() when (extract(#margin, 4) = unset), (extract(#margin, 3) = unset), (extract(#margin, 2) = unset), (extract(#margin, 1) = unset)
{
.marginComponent(#name, #value)
{
& when not (#value = unset)
{
#{name}: #value;
}
}
.marginComponent(margin-top, extract(#margin, 1));
.marginComponent(margin-right, extract(#margin, 2));
.marginComponent(margin-bottom, extract(#margin, 3));
.marginComponent(margin-left, extract(#margin, 4));
}
._smartMargin() when (default())
{
margin: #margin;
}
._smartMargin();
}
.smartMargin(#margin) when (default())
{
& when not (#margin = ~'') and not (#margin = unset)
{
margin: #margin;
}
}
You could possibly rewrite it to something like:
.smartMargin(#margin) when (isem(#margin)),(isem(extract(#margin,1))) and (isem(extract(#margin,2))) and (isem(extract(#margin,3))) and (isem(extract(#margin,4))) {
margin: #margin;
}
.smartMargin(#margin) when (default()) and (4 = length(#margin)) {
#positions: top, right, bottom, left;
.setmargin(#position,#margin) when (isem(#margin)){
margin-#{position}: #margin;
}
.setmargins(#i:1) when (#i <= 4){
.setmargin(extract(#positions,#i);extract(#margin,#i));
.setmargins((#i + 1));
}
.setmargins();
}
But in the first place i don't think there is something wrong with your code. Personally is should consider the use of unset. I think you should use the initial keyword or even 0 in stead of unset. This enables you to do the following:
.smartMargin(#margin){
margin: #margin;
}
.one{
.smartMargin(3em);
}
.two{
.smartMargin(3em 1em 2em 4em);
}
.three{
.smartMargin(3em 0 0 0);
}
.four{
.smartMargin(3em 0 0 4em);
}
Or consider to use Passing Rulesets to Mixins, than you can use something like that shown below:
.breakPoint(#width, #color, #labelsSize, #videoMargin)
{
video
{
#videoMargin();
}
}
.breakPoint(10em, red, 3em, {margin: 1em auto 1em auto;});
.breakPoint(10em, red, 3em, {margin: 1em auto;});
.breakPoint(10em, green, 3em, {margin: 2em 0 0 0;});
.breakPoint(10em, green, 3em, {margin: 2em 0 0;});
.breakPoint(10em, green, 3em, {margin-top: 2em;});
.breakPoint(20em, blue, 3em, {margin: 0 3em 0 0;});
.breakPoint(20em, blue, 3em, {margin-right: 3em;});

Resolving dynamic variables in LESS

I am trying to generate a number of classes in a loop based on a number of pre-defined variable snippets.
I have a variables.less document that I am importing at the top of this less file containing my color variables. I then want to generate matching classes for these, but I am unable to get less to compile the variable.
My code:
.loop-class(~"primary", ~"success", ~"info", ~"warning", ~"danger";);
.loop-class(#list, #index: 1) when (isstring(extract(#list, #index))) {
#status: extract(#list, #index);
.button-#{status} {
color: ~'#button-#{status}';
}
.loop-class(#list, (#index + 1));
}
Which compiles to:
.button-primary {
color: #button-primary;
}
.button-success {
color: #button-success;
}
etc etc
As you can see, I get the variable name to concatenate correctly, but I can not get it to resolve, so I'm guessing that LESS has already done it's variable compilation before getting to this function?
I have already tried moving the variables into this document, as well as wrapping the variables in a mixin and adding that inside the .loop-class, but neither of these seemed to help.
I also tried something like:
#status: extract(#list, #index);
#compileClass: ~'#button-#{status}';
.button-#{status} {
color: #compileClass;
}
where I am saving the variable in a another one and then referencing that, but it yields the same result.
I looked at less css calling dynamic variables from a loop and tried implementing that as follows:
.loop-class(~"primary", ~"success", ~"info", ~"warning", ~"danger";);
.define(#var) {
#fallback: ~'#button-#{var}';
}
.loop-class(#list, #index: 1) when (isstring(extract(#list, #index))) {
#status: extract(#list, #index);
.button-#{status} {
.define(#status);
color: ##fallback;
}
.loop-class(#list, (#index + 1));
}
But that gave me the error that ##button-danger (last in the index) is undefined, so it still can't resolve the variable.
Is it obvious to you guys what I'm doing wrong?
Thanks for your help!
Missing Brackets
You are missing a set of needed brackets to resolve the variable:
LESS
//imported from another file
#button-primary: cyan;
#button-success: green;
#button-info: orange;
#button-warning: yellow;
#button-danger: red;
//in your mixin file
.loop-class(~"primary", ~"success", ~"info", ~"warning", ~"danger";);
.loop-class(#list, #index: 1) when (isstring(extract(#list, #index))) {
#status: extract(#list, #index);
.button-#{status} {
color: ~'#{button-#{status}}'; /* two more brackets needed */
| |
here here
}
.loop-class(#list, (#index + 1));
}
CSS Output
.button-primary {
color: #00ffff;
}
.button-success {
color: #008000;
}
.button-info {
color: #ffa500;
}
.button-warning {
color: #ffff00;
}
.button-danger {
color: #ff0000;
}
Cleaner More Friendly Code
Also, as a matter of less cluttered and more user friendly code, you can remove your multiple string interpolations needed for the mixing call by changing isstring to iskeyword in your mixin:
.loop-class(primary, success, info, warning, danger;); /* cleaner code on call */
.loop-class(#list, #index: 1) when (iskeyword(extract(#list, #index))) {
#status: extract(#list, #index);
.button-#{status} {
color: ~'#{button-#{status}}';
}
.loop-class(#list, (#index + 1));
}

Define LESS variable from string

I'm trying to write a mixin that returns a variable for converting px to em. I've toyed with a few things, but ultimately i'd like to call a mixin and get a return value similar to SASS's functions. Based on on return values here: http://www.lesscss.org/#-return-values, I can only define a variable once as a return value. Example:
Mixin
.px-to-emz( #size, #base: #font-size-base ){
#em: round( unit( (#size / #base), ~"em" ), 3 );
}
Call it:
.foo {
font-size: #em;
.px-to-emz(10, 16px);
height: #em;
.px-to-emz(200, 16px);
}
Fine, if you want to only return one variable, but if i want to return multiple variables I need to define new variable names. Here's what i'd ideally like to do
Mixin:
.px-to-ems( #size, #var: 'em', #base: #font-size-base ){
~'#{var}': round( unit( (#size / #base), ~"em" ), 3 );
}
Call it:
.foo {
font-size: #font-size;
.px-to-ems(10, 'font-size', 16px);
height: #height;
.px-to-ems(200, 'height', 16px);
}
#1
So far the best known solution for this problem is to put each mixin call into its own scope:
.px-to-ems(#size, #base: #font-size-base) {
#-: round(unit((#size / #base), em), 3);
}
.foo {
.-() {font-size: #-; .px-to-ems( 10, 16px)}
.-() {height: #-; .px-to-ems(200, 16px)}
.-;
}
Replace #- and .- with whatever identifiers you find suitable.
#2
The other way around is to use recently added (Less 1.6.x) property interpolation feature:
.px-to-ems(#property, #size, #base: #font-size-base) {
#{property}: round(unit((#size / #base), em), 3);
}
.foo {
.px-to-ems(font-size, 10, 16px);
.px-to-ems(height, 200, 16px);
}
It's more clean than #1 if you simply need to assign the "function" result to a property.