LESS混合重复属性

3
当使用LESS时,我发现混合类很有用,它可以根据其他类的属性创建一个新类,但有时我需要覆盖这些属性。
例如:

.btn {
  border-radius: 10px;
  background-color: blue;
  font-size:10px;
}

.btn_warning {
  .btn;
  background-color: yellow;
  font-size: 12px;
}

The output has duplicated properties:

.btn {
    border-radius: 10px;
    background-color: blue;
    font-size:10px;
}

.btn_warning {
    border-radius: 10px;
    background-color: blue; 
    font-size:10px; 
    background-color: yellow;
    font-size: 12px;
}

我知道有多种方法可以解决这个问题,比如在dom上使用多个类,或者使用@extend来构建多个选择器,但是浏览器仍然会在运行时覆盖属性。

当使用mixin时,是否有必要复制相同的属性?这似乎是一种使属性“独立”分组的简单方法,但如果存在重复的值,则不太好看。

2个回答

6

LESS不考虑在一个块内删除重复属性,至少部分原因是由于这个原因在这里说明(引用略有修改以修正语法):

问题在于人们经常使用多个属性来为旧版浏览器提供回退。普遍地删除这些属性并不是好的做法。

程序员需要自己避免重复编写代码。你可以像Danny Kijkov在他的答案中所指出的那样设置一个基本mixin,或者...

解决方案#1(复杂但功能强大)

你可以构建一个复杂的主按钮制作mixin。像这样:

LESS(Mixin)

.makeBtn(@ext: null; @rad: 10px; @color: blue; @size: 10px;) {
  .set-extension() when (@ext = null) {
    @class-extension: ~'';
  }
  .set-extension() when not (@ext = null) {
    @class-extension: ~'_@{ext}';
  }
  .set-extension();

  .btn@{class-extension} {
    border-radius: @rad;
    background-color: @color;
    font-size: @size;

    //define various addtions based on extensions here
    .specialExtensionProps() when (@ext = danger) {
      border: 3px solid red;
    }
    .specialExtensionProps() when (@ext = someExtName) {
      my-special-prop: yep;
    }
    .specialExtensionProps();
  }  
}

LESS (使用Mixin的多种方式)

.makeBtn(); //makes base button
.makeBtn(warning; @color: yellow; @size: 12px); //makes modified button 
.makeBtn(danger; @color: red;); //makes modified button
.makeBtn(someExtName, 15px); //makes modified button

CSS输出

.btn {
  border-radius: 10px;
  background-color: #0000ff;
  font-size: 10px;
}
.btn_warning {
  border-radius: 10px;
  background-color: #ffff00;
  font-size: 12px;
}
.btn_danger {
  border-radius: 10px;
  background-color: #ff0000;
  font-size: 10px;
  border: 3px solid red;
}
.btn_someExtName {
  border-radius: 15px;
  background-color: #0000ff;
  font-size: 10px;
  my-special-prop: yep;
}

如果您不知道,上面演示了LESS功能,仅从mixin变量集中设置一些变量。因此,对于前两个专门的.makeBtn()调用,我只设置了一些变量,这些变量是无序的,并通过显式调用变量名称进行设置(例如@color: yellow)。这使我能够“跳过”设置@size。在最后一个示例中,我仅设置了前两个值,因此不需要放置任何变量名称。
我不知道上述内容是否有助于您获得所需内容,但它确实提供了一种不同的减少代码大小的方法。

解决方案#2

您提到了:extend(),它可以很好地用于避免重复:
.btn {
  border-radius: 10px;
  background-color: blue;
  font-size:10px;
}

.btn_warning {
  &:extend(.btn);
  background-color: yellow;
  font-size: 12px;
}

CSS输出

.btn,
.btn_warning {
  border-radius: 10px;
  background-color: blue;
  font-size: 10px;
}
.btn_warning {
  background-color: yellow;
  font-size: 12px;
}

解决方案 #3

在您的情况下,如果所有按钮都是.btn.btn_SOMETHING形式的类,且您没有将.btn_用于除按钮之外的任何内容,则可以使用CSS级联来应用样式并防止CSS代码的重复。无需特殊的LESS(Less is More):

LESS和CSS输出结果

.btn, [class *= btn_] {
  border-radius: 10px;
  background-color: blue;
  font-size:10px;
}

.btn_warning {
  background-color: yellow;
  font-size: 12px;
}

任何带有类名为btn_warning的HTML元素将首先从属性选择器[class *= btn_]获取基本按钮样式,而实际的btn_warning类将覆盖要被覆盖的内容。

解决方案 #4

如果您在HTML中拆分类名(因此使用class="btn warning"而不是class="btn_warning"),则可以避免重复:

LESS和CSS输出

.btn {
  border-radius: 10px;
  background-color: blue;
  font-size:10px;
}

.btn.warning {
  background-color: yellow;
  font-size: 12px;
}

现在我明白了原因,非常感谢您的回答。就浏览器性能而言,您认为总体而言,像解决方案#1中生成的大而冗余的单个类输出是否比像#2、#3或#4中生成的更复杂的选择器更好?似乎是大小与CPU之间的关系。由于我正在预处理,所以我觉得输出必须是“丑陋”的但优化的。如果您想发表意见,请告诉我。 - user2783677
就我个人而言,如果可以修改HTML,我会选择第四种方案。否则,我可能会使用第二种方案。但这完全取决于具体应用场景。在渲染过程中,CPU 时间几乎是无关紧要的。 - ScottS

3
这个解决方案怎么样?
.btn(@size: 10px, @color:blue) {
    border-radius: 10px;
    background-color: @color;
    font-size:@size;
}

.btn_warning {
    .btn(12px, yellow);
}

谢谢似乎是在混合中覆盖类属性时避免重复的最佳方式,但需要更费力地提醒参数。仍然在思考是否需要这种行为,或者可以请求维护已定义属性的字典以避免重复。 - user2783677

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