如何在LESS CSS中创建嵌套循环?

7

我知道的是这样的:

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

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

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

…将导致以下结果:

.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%}

使它成为 LESS 的等效物,即:
for (var i = 8; i > 0; -- i) {
  // …
}

我的问题是:如何用LESS实现以下代码的效果:
for (var i = 8; i > 0; -- i) {
  for (var j = 4; j > 0; -- j) {
    // …
  }
}

看起来像什么?

4个回答

12

嗯,没事了——我自己找到了。

我会把答案留在这里,供后人参考:

@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);

5
.i-loop (0) {} 的目的是什么?我在不加它的情况下尝试了这段代码,它可以工作。 - Nico Prat

1

一个非嵌套的解决方案

我在这里只是提供一种最终输出代码的替代方法。我的答案并没有直接解决循环嵌套的问题(正如你的问题和你自己的答案所找到的解决方案)。相反,它挑战了是否嵌套甚至是解决你所面临的问题的最佳方法。

假设类结构与您拥有的一样(例如 my-class-2-6),您可以通过不嵌套它们,而是使用CSS3属性选择器(取决于您需要支持的目标浏览器,可能不是理想的选择)将64个输出CSS选择器减少到仅16个。因此,这个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);

变成了这个 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%;
}

所以 my-class-2-6 的例子将会选中类名 my-class-2 的开头,设置 width: 50%,并且选择类名的结尾 -6,然后设置 height: 16.666666666666668%;
对于任何未来可能面临相似情况的用户,这只是一个建议,他们只需要关注针对 CSS3 浏览器进行定位。
更新:添加了保护措施以避免错误的定位。
事后想到,如果您有多种类型的类,可能会以 -1-2 等结尾,则您的 CSS 结尾可能需要具有额外的代码来仅帮助过滤该类。因此,上述循环代码中的选择器字符串需要更改为如下形式:
@{iSelStart}@{ijSelEnd}@{jSelStart}@{j}@{ijSelEnd}  { /*properties*/}

然后会输出这种代码格式:
[class^=my-class-][class$=-1] {
  /*properties*/
}

这样,它会特别查找以-1结尾的my-class-类,并忽略选择另一个类似于another-class-1的类,因为原始代码仍然会选择。是否存在问题纯粹取决于网站设计和类命名的使用。

谢谢。这很有趣。 - Cristian
请注意--我刚刚在代码更改中添加了一个想法,以防止在某些情况下选择不当的保护措施可能是相关的。 - ScottS

0

虽然这是一个老问题,但也许值得一提的是,现在Less可以更轻松地实现这个功能。

函数

.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)}

使用方法

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

示例:Codepen



0
.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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接