Concatenating arbitrary number of values in lesscs

2019-02-14 16:30发布

问题:

Standard lesscss mixin:

.box-shadow(@val) {
    -moz-box-shadow: @val;
    box-shadow: @val;
}

However, in pure CSS I'm able to use several box shadows on one element, e.g.

#myBox {
    box-shadow: inset 0px 1px 0px white, 0px 0px 5px #aaa;
    -moz-box-shadow: inset 0px 1px 0px white, 0px 0px 5px #aaa;
}

To ie. create an inset and glow effect. Of course I want to use lesscss to remedy the vendor-prefix curse in this case too, but

.box-shadow() {
    -moz-box-shadow: @arguments;
    box-shadow: @arguments;
}

#myBox {
    .box-shadow(inset 0px 1px 0px white, 0px 0px 5px #aaa);
}

will render

#myBox {
    box-shadow: inset 0px 1px 0px white 0px 0px 5px #aaa;
    -moz-box-shadow: inset 0px 1px 0px white 0px 0px 5px #aaa;
}

(notice the missing commas after white)! Which is syntactically incorrect. Is there any way to trick lesscss into concatenating multiple arguments with , instead of ? I thought this should be a more-or-less standard problem, but haven't found any canonical solutions...

回答1:

Use an escaped string

#myBox { .box-shadow(~"inset 0px 1px 0px white, 0px 0px 5px #aaa"); }

Or a javascript escape

Less 1.2.0 and below:

.box-shadow() {
    @shadow: ~`'@{arguments}'.replace(/[\[\]]/g, '')`;
    -webkit-box-shadow: @shadow;
       -moz-box-shadow: @shadow;
            box-shadow: @shadow;
}
#myBox { .box-shadow(inset 0px 1px 0px white, 0px 0px 5px #aaa); }

Less 1.3.0 and above (requires and uses ... variadic specifier):

.box-shadow(...) {
    @shadow: ~`'@{arguments}'.replace(/[\[\]]/g, '')`;
    -webkit-box-shadow: @shadow;
       -moz-box-shadow: @shadow;
            box-shadow: @shadow;
}

The author's recommended way is an intermediate variable:

#myBox {
  @shadow: inset 0px 1px 0px white, 0px 0px 5px #aaa;
  .box-shadow(@shadow);
}


回答2:

If you escape the argument string as a string literal, it will carry the comma over just as you want:

.box-shadow() {
    -moz-box-shadow: @arguments;
    box-shadow: @arguments;
}

#myBox {
    .box-shadow(~"inset 0px 1px 0px white, 0px 0px 5px #aaa");
}

Outputs:

#myBox {
  -moz-box-shadow: inset 0px 1px 0px white, 0px 0px 5px #aaa;
  box-shadow: inset 0px 1px 0px white, 0px 0px 5px #aaa;
}


回答3:

If you are using lessphp (http://leafo.net/lessphp/) for server side compilation (instead of the javascript lesscss compiler from http://lesscss.org) you could bind a php function and use it to change the character used for the concatenation.

Example lesscss code:

.linear-gradient(@fallback, @deg, @tail...) {
    background-color: @fallback;
    background-image: linear-gradient(@deg, separateByComma(@tail));
    background-image: -webkit-linear-gradient(@deg, separateByComma(@tail));
    background-image: -moz-linear-gradient(@deg, separateByComma(@tail));
    background-image: -o-linear-gradient(@deg, separateByComma(@tail));
}

body {
    .linear-gradient(#FCFCDD, 135deg, #FCFCDD, #FFFFFF 66%, #FCFCDD);
}

Bound php function:

function lesscss_separateByComma($arg) {
    if($arg[0]=='list')
            $arg[1]=',';
        return $arg;
}

And to do the binding and compile the lesscss code:

$less=new lessc();
$less->registerFunction('separateByComma', 'lesscss_separateByComma');
$code=$less->compile($code);

Output:

body {
  background-color: yellow;
  background-image: linear-gradient(135deg,#FCFCDD,#FFFFFF 66%,#FCFCDD);
  background-image: -webkit-linear-gradient(135deg,#FCFCDD,#FFFFFF 66%,#FCFCDD);
}

Tested with lessphp 0.4.0.



回答4:

Using the solution found here works with one AND multiple arguments:

.box-shadow (@value1,@value2:X,...)
{
    @value: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`;

    -webkit-box-shadow: @value;
    -moz-box-shadow: @value;
    -ms-box-shadow: @value;
    -o-box-shadow: @value;
    box-shadow: @value;
}


标签: css less