How do I create nested loops with LESS CSS?

半城伤御伤魂 提交于 2019-12-07 03:11:33

问题


What I know is that this:

@iterations: 8;
.mixin-loop (@index) when (@index > 0) {

  .my-class-@{index} {
     width: (100% / @index);
  }

  .mixin-loop(@index - 1);
}
.mixin-loop (0) {}
.mixin-loop(@iterations);

… Will result in this:

.my-class-8{width:12.5%}
.my-class-7{width:14.285714285714286%}
.my-class-6{width:16.666666666666668%}
.my-class-5{width:20%}
.my-class-4{width:25%}
.my-class-3{width:33.333333333333336%}
.my-class-2{width:50%}
.my-class-1{width:100%}

… Making it the LESS equivalent of:

for (var i = 8; i > 0; -- i) {
  // …
}

My question is: What would the LESS equivalent of:

for (var i = 8; i > 0; -- i) {
  for (var j = 4; j > 0; -- j) {
    // …
  }
}

… Look like?


回答1:


Hm, nevermind—Found it myself.

I’m leaving the answer here for posterity’s sake:

@maxi: 8;
.i-loop (@i) when (@i > 0) {

  @maxj: 8;
  .j-loop (@j) when (@j > 0) {

    .my-class-@{i}-@{j} {
      width: (100% / @i);
      height: (100% / @j);
    }

    .j-loop(@j - 1);
  }
  .j-loop (0) {}
  .j-loop(@maxj);

  .i-loop(@i - 1);
}
.i-loop (0) {}
.i-loop(@maxi);



回答2:


An Unnested Solution

I'm only offering this as an alternative here for final output code purposes. My answer does not really address nesting of loops directly (as your question is and your own answer found that solution). Rather, it challenges whether nesting is even best to solve the problem you faced.

Assuming a class structure just as you have (say my-class-2-6 for example), you can reduce from 64 output CSS selectors to just 16 by not nesting them and instead using CSS3 attribute selectors (which may not be desirable, depending on target browsers you need to support). Thus this LESS:

@maxi: 8;
@maxj: 8;
@iSelStart: ~'[class^=my-class-';
@jSelStart: ~'[class$=-';
@ijSelEnd: ~']';
.i-loop (@i) when (@i > 0) {

  @{iSelStart}@{i}@{ijSelEnd} {
     width: (100% / @i);
  }
  .i-loop(@i - 1);
}

.j-loop (@j) when (@j > 0) {

  @{jSelStart}@{j}@{ijSelEnd}  {
    height: (100% / @j);
  }

  .j-loop(@j - 1);
}
//stop loops
.i-loop (0) {}
.j-loop (0) {}
//itialize loops
.j-loop(@maxj);
.i-loop(@maxi);

Becomes this CSS:

[class$=-8] {
  height: 12.5%;
}
[class$=-7] {
  height: 14.285714285714286%;
}
[class$=-6] {
  height: 16.666666666666668%;
}
[class$=-5] {
  height: 20%;
}
[class$=-4] {
  height: 25%;
}
[class$=-3] {
  height: 33.333333333333336%;
}
[class$=-2] {
  height: 50%;
}
[class$=-1] {
  height: 100%;
}
[class^=my-class-8] {
  width: 12.5%;
}
[class^=my-class-7] {
  width: 14.285714285714286%;
}
[class^=my-class-6] {
  width: 16.666666666666668%;
}
[class^=my-class-5] {
  width: 20%;
}
[class^=my-class-4] {
  width: 25%;
}
[class^=my-class-3] {
  width: 33.333333333333336%;
}
[class^=my-class-2] {
  width: 50%;
}
[class^=my-class-1] {
  width: 100%;
}

So the example of my-class-2-6 would target the start of the class name my-class-2 giving a width: 50% and target the end of the class name -6 which would give a height: 16.666666666666668%;.

Just a thought for any future users facing a similar situation who are only worried about targeting CSS3 browsers.

Update: Added Protection to not Incorrectly Target

As an after thought, it occurred to me that if you have various types of classes that may have an ending of -1 or -2 etc., then your ending CSS may need to have an additional set of code to help filter for just that class. So the j loop code above would need to have a change to the selector string like so:

@{iSelStart}@{ijSelEnd}@{jSelStart}@{j}@{ijSelEnd}  { /*properties*/}

Which would then output this format of code:

[class^=my-class-][class$=-1] {
  /*properties*/
}

This way it is looking specifically for the my-class- "class" that ends in -1, and would ignore selecting another class like another-class-1 as the original code above would still select. Whether this is an issue or not would purely be related to the design and class naming used in one's site.




回答3:


Old question but maybe it's worth mentioning that Less can now do this easier

Function

.for(@i, @n, @r){@r();._(@i)}
.for(@n, @r)when(isnumber(@n)){.for(0, @n, @r)}
.for(@i, @n, @r)when not(@i = @n - 1){.for((@i + ((@n - @i) / abs(@n - @i))), @n, @r)}

Usage

.for(3, {._(@i) {
  .for(3, {._(@j) {
    item-@{i}-@{j} {
      i: @i;
      j: @j;
    }
  }});
}});

Example: Codepen




回答4:


.loop(@n: 1, @m: @n, @k: @n * @m) when(@k > 0) {
    .loop(@n, @m, @k - 1);

    @i: `Math.floor((@{k} - 1) / @{m})`;
    @j: @k - @i * @n - 1;

    /*
        @i runs up 1 to @n,
        @j runs up 1 to @m and
        @k runs up 1 to @n * @m

        for example:
    */

    &:nth-child(@{k}) {
        top: 50px * @i;
        left: 100px * @j;
    }
}

/* using: */
.loop(3,4);


来源:https://stackoverflow.com/questions/17011090/how-do-i-create-nested-loops-with-less-css

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!