EDIT: 这个问题被标记为this one的副本,但请参阅本答案末尾附近的附录,以了解该问题的答案是什么't ask, and what the answer doesn' .
我正在使用一个使用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
在理论上足够简单,但由于我称之为“变量依赖”而出现问题 - 变量被定义为其他变量 . 例如:
$brand: blue;
$text: $brand;
现在,让's say the above variables are defined in _variables.scss. Then let'在_app-variables.scss中说,我只覆盖$ brand变量使其变为红色: $brand: red
. 由于SASS按顺序逐行解释代码,它首先将$ brand设置为蓝色,然后将$ text设置为蓝色(因为$ brand在此时为蓝色),最后将$ brand设置为红色 . 因此最终结果是,之后更改$品牌不会影响任何基于旧品牌 Value 的变量:
_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.
但显然这不是我想要的 - 我希望我的$品牌改变能够影响所有依赖它的东西 . 为了正确覆盖变量,我现在只是将_variables.scss的完整副本复制到_app-variables.scss中,然后在_app-variables中进行修改 . 同样地,我将_app-variables.scss的完整副本复制到_client-variables.scss中,然后在_client-variables.scss中进行修改 . 从维护的角度来看,这显然不太理想(轻描淡写) - 每当我对_variables.scss(在Bootstrap升级的情况下)或_app-variables.scss进行修改时,我都必须手动涓流改变文件覆盖堆栈 . 此外,我不得不重新宣布一些我甚至可能无法克服的变量 .
我发现LESS有他们所谓的"lazy loading"(http://lesscss.org/features/#variables-feature-lazy-loading),其中变量的最后一个定义在任何地方使用,甚至在最后一个定义之前 . 我相信这会解决我的问题 . 但有没有人知道使用SASS的适当的变量覆盖解决方案?
ADDENDUM:
这里's one technique I'已经考虑过:以相反的顺序包含文件,使用 !default
表示所有变量(这个技术也在this question的答案中提出) . 所以这是如何发挥作用:
_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)
所以这个解决方案是完美的 . However ,现在在我的覆盖文件中,我没有't have access to variables defined in Bootstrap' s _variables.scss,如果我想使用其他Bootstrap变量来定义我的变量覆盖(或我自己的其他自定义变量),我将需要它 . 例如,我可能想要这样做: $custom-var: $grid-gutter-width / 2;
4 回答
解决了,但我不知道这个版本的工作原理 . 我相信解决方案始终可用 . 测试:
我们将使用简化的环境,因此文件名与Bootstrap不匹配 .
挑战
给定一个我们无法控制的框架(例如,仅在Continuous Integration环境中安装,在我们的机器中不可用),它以下列方式表示SCSS变量:
并在同一框架中给出一个使用变量的文件:
挑战是:
更确切地说:
解决方案
主文件看起来像这样:
你的变量文件看起来像这样:
结果:
解释
%scope
部分不是SCSS的神奇之处,它只是一个名为scope
的隐藏类,专门用于@extend
的后续扩展 . 我们正在使用它来创建一个变量范围(因此名称) .在范围内我们
@import
框架的变量 . 因为此时每个变量都没有值,每个变量都被创建并分配给它!default
值 .But here’s the gimmick. 变量 are not global, but local . 我们可以访问它们,但它们不会污染全局范围,后者将用于在框架内派生变量 .
实际上,当我们想要定义变量时,我们希望它们是全局变量,实际上我们使用
!global
关键字来指示SCSS将它们存储在全局范围内 .警告
有一个主要的警告: you cannot use your own variables while you define them .
这意味着在这个文件中
@debug
语句将打印在boostrap / _variables.scss中定义的 the default value ,而不是black
.解决方案
拆分变量分为两部分:
第二个
@debug
确实会正确打印black
.使用Bootstrap 4或bootstrap-sass,使用!default标志在_variables.scss中设置所有变量 .
因此,如果在包含bootstrap的_variables.scss之前设置变量,则在包含该变量时,将忽略_variables.scss中的值 .
所以我的sass条目文件可能看起来像这样......
@import "bootstrap-overrides"; @import "bootstrap/scss/bootstrap-flex"; @import "mixins/module";
在Bootstrap 4的alpha 6中,_variables.scss中的所有变量都可以在_custom.scss中被覆盖,就像mryarbles描述的那样 . 但是,覆盖不会级联到其他元素,因为包含顺序是:
当我改变这个
它按预期工作 .
BS4 dev分支中的
_custom.scss
文件已被删除 . 尝试使用此订单重新排序您的导入:Setup
确保将boostrap变量文件
_variables.scss
的内容复制到app-variables
和client-variables
. 在每个变量旁边留下!default以允许进一步覆盖 .Explanation
所有引导变量都使用
!default
声明 . 来自Sass reference:Bootstrap将尊重已在顶部定义的所有变量,使
app_variables
具有更高优先级,client_variables
具有最高优先级 .您需要将bootstrap
_variables
中的所有变量声明复制到app-variables
和client-variables
中,以便您可以根据需要使用自定义变量 . (缺点是每次引导更新都很难维护)所有变量现在都在
app-mixins
和client-mixins
中可用