用于在twitter中生成列类的LESS循环 - 它们如何工作?

时间:2014-08-14 11:00:34

标签: css3 twitter-bootstrap loops less

Bootstrap使用一些LESS mixins来生成它的column类(以及其他几个类);

.make-grid-columns() {
  // Common styles for all sizes of grid columns, widths 1-12
  .col(@index) when (@index = 1) { // initial
    @item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}";
    .col((@index + 1), @item);
  }
  .col(@index, @list) when (@index =< @grid-columns) { // general; "=<" isn't a typo
    @item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}";
    .col((@index + 1), ~"@{list}, @{item}");
  }
  .col(@index, @list) when (@index > @grid-columns) { // terminal
    @{list} {
      position: relative;
      // Prevent columns from collapsing when empty
      min-height: 1px;
      // Inner gutter via padding
      padding-left:  (@grid-gutter-width / 2);
      padding-right: (@grid-gutter-width / 2);
    }
  }
  .col(1); // kickstart it
}

我可以看到LESS mixin guards被用来创建循环,我可以理解LESS documentation中给出的代码示例;

.loop(@counter) when (@counter > 0) {
  .loop((@counter - 1));    // next iteration
  width: (10px * @counter); // code for each iteration
}

div {
  .loop(5); // launch the loop
}

但我似乎无法确切地知道bootstrap使用的更复杂的嵌套保护表达式是如何工作的。有人可以更详细地评论上面的引导代码,以便告诉我发生了什么事吗?

1 个答案:

答案 0 :(得分:1)

.make-grid-columns() mixin的目的是生成一长串选择器,它们共享相同的属性。 此列表不能是代码中的硬代码,因为列数(@grid-columns)可能会有所不同。

您已经在问题中用Less来说明循环的基础知识。

要了解mixins,您必须了解Less允许您多次使用相同的mixin名称。 每个匹配的&#39; mixins将被编译成CSS代码。 Mixin guards when ()使您能够为匹配设置条件。当守卫不匹配时,mixin不会被编译。 除了mixins防护之外,您还可以使用模式匹配,而不是按照以下方式匹配值:

.mixin1(a,@width){}
.mixin1(b,@width){}

.mixin(a,20px);来电仅匹配第一个混音。基于arity(参数个数)的Partern匹配将 也有效。请注意,.col(@index) when (@index = 1)不需要警卫(see also)。 .col(@index)调用只有一个参数,因此.col(1);仅匹配基于arity匹配的mixin。 .col(@index) mixin调用.col(@index, @list) mixin(s)。 .col(@index) when (@index = 1) mixin仅在第一次迭代时被调用。有两个mixin而不是一个mix的原因是Less不支持if / else。选择器列表不能以逗号开头或结尾,因此选择器列表中的第一个或最后一个项应该与其他项不同。

或者你可以使用带有附加参数的mixin:

.mixin(@iterator; @item:~""; @seperator:~"") when (@iterator < 5){
@list: ~"@{item} @{seperator} @{iterator}";
.mixin((@iterator + 1); @list; ",");
}
.mixin(@iterator; @list; @seperator) when (@iterator = 5){
.selector{
@{list}: value;
}
}
.mixin(1);

@seperator对于第一次调用将为空(~""),对于所有其他调用将为逗号(",")。 请注意,具有默认参数的mixin也匹配没有默认设置值的调用: 因此.call(1);.call(@a; @b:4; @c:5){} mixin相匹配。

正如评论中已经提到的那样~"@{list}, @{item}"通过字符串连接生成选择器列表。

.col(@index, @list) when (@index =< @grid-columns)时,col((@grid-columns + 1)....)调用@index=@grid-columns的最后一次调用mixin与结构中的最后一个.col(@index, @list) when (@index > @grid-columns) mixin匹配。

@{list} { }使用选择器插值来设置选择器列表及其属性。

当然,您还应该阅读关于此结构的@ 7-phases-max的excellent blog post以生成选择器列表。

最后你应该知道Bootstrap需要这么长的选择器列表,因为它避免了(部分)属性选择器。您可以使用以下CSS / Less代码代替选择器列表:

[class^="col-"], [class*=" col-"]
{
      position: relative;
      // Prevent columns from collapsing when empty
      min-height: 1px;
      // Inner gutter via padding
      padding-left:  (@grid-gutter-width / 2);
      padding-right: (@grid-gutter-width / 2);
}

避免使用属性选择器的原因是某些浏览器计算速度很慢。从http://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/可以看出,你可以讨论这个论点。我个人认为,在大多数Bootstrap项目中,未使用的代码比使用属性选择器更重要。