Search code examples
csslessmixins

Append string in LESS variable


I want to dynamicaly call .some-mixin() with some colors. This mixins should generate some styles, and when the colors are equals the special code should be generated.

Due to comprimation of final css code I want to do it by help variable, where can I store classes for the special code.

Maybe sample code will be more helpful:

.some-mixin(@newClass,@color,@color2){
      .test-mixin(@newClass,@color,@color2);
      .@{newClass}{
         color: @color;
      }
}

@classes: '';
.test-mixin(@newClass,@color,@color2) when (@color = @color2){
    @classes: "@{classes}, @{newClass}";
}
.final-mixin(){
    .@{classes}{
        /*some styles*/
    }
}

The call of mixins is generated by PHP and final code should looks like this:

.some-mixin("abc",#ffffff,#000000);
.some-mixin("xyz",#ffffff,#ffffff);
.some-mixin("jkl",#ff00ff,#ff00ff);
.final-mixin();

But when I want compile the LESS it shows infinite loop detected

Is this possible in LESS?

Any advice will be helpul.


Solution

  • As explained in comments, your problem is the recursive variable definition in the below line. Less does not support this as explained in this answer and this one.

    @classes: "@{classes}, @{newClass}";
    

    Based on your requirement explanation in comments (that there would be some extra padding etc when the colors are different), you could use one of the below methods.

    Option 1: (will add the padding to every class and so repeated code)

    .some-mixin(@newClass,@color,@color2){
          .@{newClass}{
             color: @color;
             & when not (@color = @color2){
                padding: 4px;
            }
          }
    }
    
    .some-mixin(abc,#ffffff,#000000);
    .some-mixin(xyz,#ffffff,#ffffff);
    .some-mixin(jkl,#ff00f0,#ff00ff);
    

    The above Less would compile into below CSS:

    .abc { 
      color: #ffffff;
      padding: 4px; /* colors were different */
    }
    .xyz {
      color: #ffffff;
    }
    .jkl {
      color: #ff00f0;
      padding: 4px; /* colors were different */
    }
    

    Option 2: (uses a dummy class + extend and so lesser code)

    This option is probably what you are looking for as it avoids code repetition. We cannot extend a mixin and hence we use a dummy class. This should not be a big concern because it just adds one extra line to output CSS.

    .common-padding-diff-color{ /* all styles that are needed when colors are different */
        padding: 4px;
    }
    .some-mixin(@newClass,@color,@color2){
          .@{newClass}{
             color: @color;
             & when not (@color = @color2){
                &:extend(.common-padding-diff-color);
            }
          }
    }
    
    .some-mixin(abc,#ffffff,#000000);
    .some-mixin(xyz,#ffffff,#ffffff);
    .some-mixin(jkl,#ff00f0,#ff00ff);
    

    This would compile into

    .common-padding-diff-color,
    .abc,
    .jkl {
      padding: 4px; /* style applied for all cases where colors are not same */
    }
    .abc {
      color: #ffffff;
    }
    .xyz {
      color: #ffffff;
    }
    .jkl {
      color: #ff00f0;
    }