Flirt Flirt - 6 months ago 27
CSS Question

Less Mixin iteration infinite (circular loop)

How do I iterate a mixin-loop without stop? Let's say I have an array with four colors. When it iterate to the last color, it begins with the first color and so on and fourth.

My code:

@array: blue, red, green, yellow;

.color-mix(@i) when (@i > 0) {
ul {
li:nth-child(@{i}) {
.background-color(extract(@array, @i);
}
}
.color-mix(@i - 1);
}

.color-mix(4);


Will only iterate four times, If I add more iterations it will break because the color-array is only four colors, am I correct? But how do I do an infinite loop?

Answer

You can do this using a bit of math on the index that is passed to the extract function. In the below snippet, I've used the mod function to make sure the index is always between 0 to 3 irrespective of what the value of @i is.

The extract function's index is 1 based (as in 1-4) but the mod function's output is 0-3 and so I've used a guard to set the index as length of the array (which is, 4) when the mod function's output is 0. I am sure there must be some math formula to get around this too but I couldn't figure that out.

The mixin will adapt even if the no. of values in the @array variable increases as I've used the array length instead of hard-coding values.

@array: blue, red, green, yellow, orange;

.color-mix(@i) when (@i > 0) {
  ul {
    li:nth-child(@{i}) {
      @temp: mod(@i, length(@array)); /* for the cycle */

      & when not (@temp = 0){
        @color: color(extract(@array, @temp));
        .background-color(@color);
        &:hover{
          .background-color(darken(@color, 5.5%));
        }
      }

      & when (@temp = 0){ /* required since n mod n = 0 but we need n */
        @color: color(extract(@array, length(@array)));
        .background-color(@color);
        &:hover{
          .background-color(darken(@color, 5.5%));
        }        
      }
    }
  }
  .color-mix(@i - 1);
}

.color-mix(8); /* you can give any number here and it will iterate in a cyclic manner */

.background-color(@color){
  background: @color;
}