1

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?

Harry
  • 87,580
  • 25
  • 202
  • 214
maverick
  • 800
  • 2
  • 13
  • 30
  • I am curious on why would you want to do that unless you are thinking of crashing somebody's system. – Harry May 24 '16 at 12:53
  • @Harry, I don't. But let's say I have a unsorted list, I want to add the colors to its background, and when it is more than four li-elements, I want it to begin from the first color again... Do you understand where I'm getting at? – maverick May 24 '16 at 12:55
  • Ok, so you are coming more to *When it iterate to the last color, it begins with the first color and so on and fourth.* than a really *infinite loop* right? I mean, you are looking more for a circular loop than an infinite? – Harry May 24 '16 at 12:56
  • @Harry, yeah pretty much. Circular loop sounds more convenient... – maverick May 24 '16 at 12:57

1 Answers1

3

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;
}
Harry
  • 87,580
  • 25
  • 202
  • 214
  • Thanks. It works... Only one issue though. On hover I have this: .background-color(darken(extract(@array, @i), 5,5%);... Getting syntax error. Why? – maverick May 24 '16 at 14:01
  • @Flirt: You're welcome. Coming to the question, do you mean you do that for every `li`? If yes, give me sometime and I will add that also into the answer. – Harry May 24 '16 at 14:03
  • That's quite verbose for my taste, could be [like this](http://less2css.org/#%7B%22less%22%3A%22%40array%3A%20blue%2C%20red%2C%20green%2C%20yellow%3B%5Cn%5Cn.color-mix(%40i)%20when%20(%40i%20%3E%200)%20%7B%5Cn%20%20%20%20.color-mix(%40i%20-%201)%3B%5Cn%20%20%20%20ul%20li%3Anth-child(%40%7Bi%7D)%20%7B%5Cn%20%20%20%20%20%20%20%20%40j%3A%20mod(%40i%20-%201%2C%20length(%40array))%20%2B%201%3B%5Cn%20%20%20%20%20%20%20%20%20background-color%3A%20extract(%40array%2C%20%40j)%3B%5Cn%20%20%20%20%7D%5Cn%20%20%20%20%5Cn%7D%5Cn%5Cn.color-mix(13)%3B%22%7D) instead. – seven-phases-max May 24 '16 at 20:59
  • 1
    Also it's important to note that if it's *circular* color (or whatever property) assignment it's more efficient to use `nth-child(Xn + Y)` instead of just `nth-child(X)` (e.g. like [there](http://codepen.io/seven-phases-max/pen/tKdAm?editors=1100)). – seven-phases-max May 24 '16 at 21:06
  • You are right on both counts @seven-phases-max. The mod function fix is something that I already mentioned in the answer as pending. And I don't know how I forgot about ax+b pattern. Will update answer when I get on to my system in the morning :) – Harry May 24 '16 at 21:24