3

I found this example in LESS documentation:

LESS:

.generate-columns(4);

.generate-columns(@n, @i: 1) when (@i =< @n) {
  .column-@{i} {
    width: (@i * 100% / @n);
  }
  .generate-columns(@n, (@i + 1));
}

OUTPUT CSS:

.column-1 {
  width: 25%;
}
.column-2 {
  width: 50%;
}
.column-3 {
  width: 75%;
}
.column-4 {
  width: 100%;
}

This loop generates 4 different divs because '4' was the value passed by firs mixin's call, but generated values are entirely calculated inside mixin. In other words, @n implicitly indicates "number of iterations".

I would like to be able to set a sort of "array of values" such as:

PSEUDO-CODE:

.generate-columns( [25,50,75,100] );

that should be passed to loop mixin and then generates the same CSS code, using each array's value. Is it possible?

Harry
  • 87,580
  • 25
  • 202
  • 214
Luca Detomi
  • 5,564
  • 7
  • 52
  • 77

2 Answers2

1

You can pass an array list to the mixin and then use the extract function to extract the value corresponding to the iteration number and use it.

.generate-columns(@n: 4; @list: 10, 20, 30, 40 );

.generate-columns(@n; @i: 1; @list) when (@i =< @n) {
  .column-@{i} {
    width: percentage((extract(@list, @i)/100)); /* built-in function to convert numeric to percentage */
  }
  .generate-columns(@n; (@i + 1);  @list);
}

or like below (basically same functionality as the above one with the only difference being that in the above snippet we are using named parameters feature because we are skipping providing a value for the @i variable in the mixin call.)

@widths: 10, 20, 30, 40, 50;

.generate-columns(5; 1; @widths);

.generate-columns(@n; @i: 1; @list) when (@i =< @n) {
  .column-@{i} {
    width: percentage((extract(@list, @i)/100));
  }
  .generate-columns(@n; (@i + 1);  @list);
}
Harry
  • 87,580
  • 25
  • 202
  • 214
  • Thank you for your solution. I accepted VSB's one only because it's more declarative and, for me, easier to read and understand, not because yours could be worst, it's only a my limit :-) – Luca Detomi Jan 26 '15 at 15:53
  • 1
    @LucaDetomi: That is OK mate. You should always choose the one that suits you the best. – Harry Jan 26 '15 at 15:57
1
.generate-columns-loop(@i; @widths) when (@i <= length(@widths)) {
  .column-@{i} {
    @width: extract(@widths, @i);
    width: (@width * 1%);
  }
  .generate-columns-loop((@i + 1), @widths);
}
.generate-columns(@widths...) {
  .generate-columns-loop(1, @widths);
}

.generate-columns(25, 50, 75, 100);
vbezhenar
  • 11,148
  • 9
  • 49
  • 63
  • Good option. Now OP has two choices among our answers depending on whether they need to enhance their existing mixin or create a different one. Choices are always good :) – Harry Jan 26 '15 at 14:54
  • 2
    @vsb and @Harry, just a minor remark: you are both inconsistent about parens. If you use parens for `(@i + 1)` then you should also use those for `width` value (i.e. `width: (@width * 1%);` and `width: percentage((extract(@list, @i)/100))`) so it will compile with whatever `--strict-math` settings. If you don't use parens for `width` then don't use them for `@i + 1` as well. – seven-phases-max Jan 26 '15 at 15:33
  • 1
    Thanks for suggestion, I fixed that issue. – vbezhenar Jan 26 '15 at 15:35
  • @vsb: Thank you. could you only explain me, meaning of "`...`" in mixin's call? I did not know it. – Luca Detomi Jan 26 '15 at 15:53
  • 1
    It's used for mixins with variable number of arguments. You can read about it [here](http://lesscss.org/features/#mixins-parametric-feature-advanced-arguments-and-the-rest-variable). Basically it will convert all parameters to the list and associate it with the @widths variable. – vbezhenar Jan 26 '15 at 19:55