Search code examples
cssloopslessmixinsless-mixins

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?


Solution

  • 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 1 to length(@array) irrespective of what the value of @i is.

    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 - 1, length(@array)) + 1; /* for the cycle */
          @color: extract(@array, @temp); /* usage of separate var is personal preference */
          .background-color(@color); /* replace mixin with prop-value if mixin does only this */
          &: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;
    }
    

    Also as seven-phases-max correctly points out in his comment, using nth-child(an + b) is a much better choice than nth-child(n) for producing repeated patterns (cyclic loop).

    @array: blue, red, green, yellow, orange;
    .color-mix(@i) when (@i > 0) {
      ul {
        @index: unit(length(@array), n) ~"+" @i;
        li:nth-child(@{index}) {
          @color: extract(@array, @i);
          .background-color(@color);
          &:hover{
            .background-color(darken(@color, 5.5%));
          }
        }
      }
      .color-mix(@i - 1);
    }
    
    .color-mix(length(@array));
    
    .background-color(@color){
      background: @color;
    }