jby*_*yrd 14 css variables overriding sass twitter-bootstrap-3
编辑:这个问题被标记为重复这一个,但看到接近这个答案的末尾增编,看看这个问题不问,什么回答不回答.
我正在使用一个使用Bootstrap 3的Web应用程序.我有一个基本的3层覆盖架构,其中1)Bootstrap的_variables.scss包含核心变量,2)_app-variables.scss包含覆盖Bootstrap的基本app变量_variables.scss和3)_client-variables.scss包含覆盖_app-variables.scss的特定于客户端的自定义.#2或#3(或两者)都可以是空白文件.所以这是覆盖顺序:
_variables.scss // Bootstrap's core
_app-variables.scss // App base
_client-variables.scss // Client-specific
Run Code Online (Sandbox Code Playgroud)
在理论上足够简单,但由于我称之为"变量依赖"而出现问题 - 变量被定义为其他变量.例如:
$brand: blue;
$text: $brand;
Run Code Online (Sandbox Code Playgroud)
现在,假设上述变量在_variables.scss中定义.然后让我们说在_app-variables.scss中,我只覆盖$ brand变量使其变为红色:$brand: red.由于SASS按顺序逐行解释代码,它首先将$ brand设置为蓝色,然后将$ text设置为蓝色(因为$ brand在此时为蓝色),最后将$ brand设置为红色.因此最终结果是,之后更改$品牌不会影响任何基于旧品牌价值的变量:
_variables.scss
---------------------
$brand: blue;
$text: $brand; // $text = blue
.
.
.
_app-variables.scss
---------------------
$brand: red; // this does not affect $text, b/c $text was already set to blue above.
Run Code Online (Sandbox Code Playgroud)
但显然这不是我想要的 - 我希望我的$品牌改变能够影响所有依赖它的东西.为了正确覆盖变量,我现在只是将_variables.scss的完整副本复制到_app-variables.scss中,然后在_app-variables中进行修改.同样地,我将_app-variables.scss的完整副本复制到_client-variables.scss中,然后在_client-variables.scss中进行修改.从维护的角度来看,这显然不太理想(轻描淡写) - 每当我对_variables.scss(在Bootstrap升级的情况下)或_app-variables.scss进行修改时,我都必须手动涓流改变文件覆盖堆栈.此外,我不得不重新宣布一些我甚至可能无法克服的变量.
我发现LESS有他们所谓的"延迟加载"(http://lesscss.org/features/#variables-feature-lazy-loading),其中变量的最后一个定义在任何地方使用,甚至在最后一个定义之前.我相信这会解决我的问题.但有没有人知道使用SASS的适当的变量覆盖解决方案?
附录:
这是我已经考虑过的一种技术:以相反的顺序包含文件,!default用于所有变量(这个技术也在这个问题的答案中提出).所以这是如何发挥作用:
_app-variables.scss
---------------------
$brand: red !default; // $brand is set to red here, overriding _variables.scss's blue.
.
.
.
_variables.scss
---------------------
$brand: blue !default; // brand already set in _app-variables.scss, so not overridden here.
$text: $brand !default; // $text = red (desired behavior)
Run Code Online (Sandbox Code Playgroud)
所以解决方案几乎是完美的.但是,现在在我的覆盖文件中,我无法访问Bootstrap的_variables.scss中定义的变量,如果我想使用其他Bootstrap变量来定义我的变量覆盖(或我自己的其他自定义变量),我将需要这些变量.例如,我可能想要这样做:$custom-var: $grid-gutter-width / 2;
Pie*_*mon 17
解决了,但我不知道这个版本的工作原理.我相信解决方案始终可用.测试:
> sassc --version
sassc: 3.2.1
libsass: 3.2.5
sass2scss: 1.0.3
Run Code Online (Sandbox Code Playgroud)
我们将使用简化的环境,因此文件名与Bootstrap不匹配.
给定一个我们无法控制的框架(例如,仅在Continuous Integration环境中安装,在我们的机器中不可用),它以下列方式表示SCSS变量:
// bootstrap/_variables.scss
$brand-primary: #f00 !default;
$brand-warning: #f50 !default;
$link-color: $brand-primary !default;
Run Code Online (Sandbox Code Playgroud)
并在同一框架中给出一个使用变量的文件:
// bootstrap/main.scss
a:link, a:visited {
color: $link-color;
}
Run Code Online (Sandbox Code Playgroud)
挑战是:
以这样的方式将框架包含在您自己的应用程序的SCSS中
- 变量在框架中的依赖关系得到保留和尊重;
- 您可以依赖于默认值,但仍然可以更改框架依赖项的结果.
更确切地说:
将框架包含在应用程序的SCSS中,使其
$brand-color始终$brand-warning与其框架中的值无关.
主文件看起来像这样:
// application.scss
@import "variables";
@import "bootstrap/variables";
@import "bootstrap/main";
Run Code Online (Sandbox Code Playgroud)
你的变量文件看起来像这样:
// _variables.scss
%scope {
@import "bootstrap/variables";
$brand-primary: invert($brand-warning) !global;
}
Run Code Online (Sandbox Code Playgroud)
> sassc main.scss
a {
color: blue; }
Run Code Online (Sandbox Code Playgroud)
这%scope部分不是SCSS的神奇之处,它只是一个带有名称的隐藏类scope,专门用于以后的扩展@extend.我们正在使用它来创建一个变量范围(因此名称).
在范围内我们@import是框架的变量.因为此时每个变量都没有值,每个变量都会被创建并赋值!default.
但这是噱头.变量不是全局变量,而是本地变量.我们可以访问它们,但它们不会污染全局范围,后者将用于在框架内派生变量.
事实上,当我们想要定义变量时,我们希望它们是全局变量,实际上我们使用!global关键字来表示SCSS将它们存储在全局范围内.
有一个主要的警告:在定义变量时不能使用自己的变量.
这意味着在这个文件中
%scope {
@import "bootstrap/variables";
$brand-primary: black !global;
@debug $brand-primary;
}
Run Code Online (Sandbox Code Playgroud)
该@debug语句将打印在boostrap/_variables.scss中定义的默认值,而不是.black
拆分变量分为两部分:
%scope {
@import "bootstrap/variables";
$brand-primary: black !global;
@debug $brand-primary;
}
@debug $brand-primary;
Run Code Online (Sandbox Code Playgroud)
第二个@debug确实会正确打印black.