使用LESS覆盖CSS类变量

5

我有一个less文件,其中包含一个定义几个颜色变量的类:

.some-css-class{ 
    @color1: #E6E6E6
    @color2: #808080
    /* some other rules follow */
 }

由于这是第三方文件,我不想直接更改它。相反,我创建了自己的less文件并导入第三方文件。现在我想覆盖基础文件中定义的颜色,但我无法使其起作用。

我尝试在根级别上覆盖颜色,但这样我无法更改变量,因为它们在基础文件中的类中定义:

/* Including base styles */
@import "base.less";

@color1: #DF007B;
@color2: #00A855;

所以我尝试覆盖类内的颜色,但显然我无法通过这种方式更改它们,因为在相同范围内(.som-css-class)无法覆盖变量:

/* Including base styles */
@import "base.less";

.some-css-class {
    @color1: #DF007B;
    @color2: #00A855;
}

有什么提示可以让我如何覆盖颜色吗?

编辑:看起来没有解决方法。在我的特定情况下,我正在寻找一种覆盖angularjs模块(angular-wizard)中颜色的方法。

现在,我看到一个拉取请求已经存在以解决这个问题: https://github.com/mgonto/angular-wizard/pull/68


我认为这里指出的方法 - http://webmasters.stackexchange.com/questions/72306/how-to-override-less-colour-variables-without-creating-a-new-skin-in-mediawiki 是唯一的办法。 - Harry
你不能从其他地方覆盖本地变量(这是一种预期行为,因此编写.some-css-class代码的人决定您不需要它)。无论如何,这看起来像一个XY问题(即,您实际问题的解决方案可能取决于为什么您需要覆盖这些变量)。 - seven-phases-max
2个回答

7
让我们来考虑一下LESS编译的方式。如果您愿意,可以在https://fiddlesalad.com/less编辑器中运行任何一个示例。
这个例子中,我只是包含了一些任意颜色和一个“background”属性,以便更容易理解。当您导入base.less时,在您的文件中实际上只是加入了一些LESS规则。因此,为了澄清,如果我们“扩展”您的导入,编译成CSS之前,该文件可能如下所示:
.some-css-class{ 
  @color1: red;
  background: @color1;
}

.some-css-class {
  @color1: purple;
}

这个输出结果是什么?
.some-css-class {
  background: red;
}

为什么?你可能会说“我已经重新声明了颜色变量,难道它不应该重新编译规则吗?”然而,这并非LESS的设计原则——它是与CSS向后兼容的,因此必须在后面出现规则才能覆盖前面的规则。取而代之的是,看下面这个例子:
.some-css-class{ 
  @color1: red;
  background: @color1;
}

.some-css-class {
  @color1: purple;
  background: @color1;
}

以下是当前的输出结果:

.some-css-class {
  background: red;
}

.some-css-class {
  background: purple;
}

规则被分成两个输出,因为第二个规则在层叠中发生得更晚,所以它具有更高的优先级 - 除非该类不存在于其他地方,否则“紫色”规则将优先采用。
在LESS中,“懒加载”变量-它将始终使用从内部作用域开始找到的最后一个值。因此:
.some-css-class {
  @color1: purple;
  background: @color1;
  @color1: blue;
}

将输出:

.some-css-class {
  background: blue;
}

不幸的是,如果我们试图将您之前的规则作为mixin扩展,它会在将它们引入新类之前从每个类中解析值:

.some-css-class{ 
  @color1: red;
  background: @color1;
}

.some-css-class {
  @color1: purple;
  background: @color1;
  @color1: blue;
}

.another-css-class {
  .some-css-class();
  @color1: orange;
}

输出:

.some-css-class {
  background: red;
}
.some-css-class {
  background: blue;
}
.another-css-class {
  background: red;
  background: blue;
}

因此,“覆盖”这些值的理想方式是将原始规则集转换为参数化mixin:

.some-css-class(@color1, @color2) { 
  background: @color1;
  color: @color2;
}

.another-css-class {
  .some-css-class(red, blue);
}

最终,你的输出将是这样的:
.another-css-class {
  background: red;
  color: blue;
}

编辑:最终我建议您将原始规则从文件中复制出来(而不修改该文件),并将其更改为您版本中的mixin。最终,您将获得与扩展和覆盖新类别的变量相同的CSS净量。


好的回答,但我希望有更好的解决方案。显然没有 :( - internetzer
没问题 -- 我想知道是否为 LESS 的未来版本提出功能请求是个好主意? - bazeblackwood
这样的功能请求几乎没有任何支持。本地化是本地变量的根本目的(即,如果上面示例中的变量应该被覆盖,则它们应该移动到某个可覆盖范围。也就是说,这是特定代码库的问题,而不是语言问题)。 - seven-phases-max
我倾向于同意你的观点,@seven-phases-max。尽管对于其他人来说,在extend语句中注入变量的简写语法可能很有用,但如果多变元mixin可以做到同样的事情,这就有点无意义了。 - bazeblackwood

-1

你尝试过扩展它吗?

.new-some-css-class {
    &:extend(.some-css-class);
    @color1: #DF007B;
    @color2: #00A855;
}

2
不,我认为这根本行不通,因为.some-css-class仍将使用旧变量+这会创建一个新类,这不是OP似乎正在寻找的。 - Harry
就像@Harry所指出的那样:基类仍将使用旧变量。但是,基类在第三方组件的整个HTML中都被使用,所以很遗憾,您的解决方案不起作用。 - internetzer
1
抱歉,我提出了这个建议,因为如果您可以使用一个新的类名,那就很好了,并且它可以正常工作,但还有另一种答案可以成为您的解决方案。对于我的不好的回答感到抱歉:( - Marcos Pérez Gude

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