Bootstrap SASS变量覆盖挑战 [英] Bootstrap SASS variable override challenge

查看:72
本文介绍了Bootstrap SASS变量覆盖挑战的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑:该问题被标记为

This question was marked as a duplicate of this one, but see the addendum near the end of this answer to see what that question doesn't ask, and what the answer doesn't answer.

我正在使用使用Bootstrap 3的Web应用程序.我有一个基本的3层覆盖体系结构,其中1)Bootstrap的_variables.scss包含核心变量,2)_app-variables.scss包含基本应用程序变量覆盖Bootstrap的_variables.scss,以及3)_client-variables.scss包含覆盖_app-variables.scss的特定于客户端的自定义项. #2或#3(或两者)可以是空白文件.所以这是优先顺序:

I'm working on a web app that uses Bootstrap 3. I have a basic 3-layer override architecture, where 1) Bootstrap's _variables.scss contains the core variables, 2) _app-variables.scss contains the base app variables that override Bootstrap's _variables.scss, and 3) _client-variables.scss contains client-specific customizations that override _app-variables.scss. Either #2 or #3 (or both) can be blank files. So here's the override order:

_variables.scss // Bootstrap's core
_app-variables.scss // App base
_client-variables.scss // Client-specific

理论上很简单,但是由于我将其称为变量依赖项"而出现了问题-变量定义为其他变量.例如:

Simple enough in theory, but a problem arises because of what I'll call "variable dependencies" -- where variables are defined as other variables. For example:

$brand: blue;
$text: $brand;

现在,假设上述变量在_variables.scss中定义.然后在_app-variables.scss中说,我仅重写$ brand变量使其变为红色:$brand: red.由于SASS逐行依次解释代码,因此它将首先将$ brand设置为蓝色,然后将$ text设置为蓝色(因为$ brand在那时是蓝色的),最后将$ brand设置为红色.因此,最终结果是事后更改$ brand不会影响基于$ brand的旧值的任何变量:

Now, let's say the above variables are defined in _variables.scss. Then let's say in _app-variables.scss, I override only the $brand variable to make it red: $brand: red. Since SASS interprets the code line by line sequentially, it will first set $brand to blue, then it will set $text to blue (because $brand is blue at that point), and finally it will set $brand to red. So the end result is that changing $brand afterwards does not affect any variables that were based on the old value of $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.

但是显然那不是我想要的-我希望更改$ brand可以影响所有依赖它的东西.为了正确地覆盖变量,我目前仅将_variables.scss的完整副本复制到_app-variables.scss中,然后从这一点开始在_app-variables中进行修改.同样,我将_app-variables.scss的完整副本复制到_client-variables.scss中,然后在_client-variables.scss中进行修改.从维护的角度来看,这显然不理想(轻描淡写)-每次我对_variables.scss(在Bootstrap升级的情况下)或_app-variables.scss进行修改时,我都必须手动将更改逐滴滴入文件覆盖堆栈.而且,我不得不重新声明很多我什至无法覆盖的变量.

But obviously that's not what I want - I want my change of $brand to affect everything that depends on it. In order to properly override variables, I'm currently just making a full copy of _variables.scss into _app-variables.scss, and then making modifications within _app-variables from that point. And similarly I'm making a full copy of _app-variables.scss into _client-variables.scss and then making modifications within _client-variables.scss at that point. Obviously this is less than ideal (understatement) from a maintenance point of view - everytime I make a modification to _variables.scss (in the case of a Bootstrap upgrade) or _app-variables.scss, I have to manual trickle the changes down the file override stack. And plus I'm having to redeclare a ton of variables that I may not even be overriding.

我发现LESS具有所谓的延迟加载"( http://lesscss.org/features/#variables-feature-lazy-loading ),其中变量的最后定义在所有地方都使用,甚至在最后定义之前也是如此.我相信这可以解决我的问题.但是,有谁知道使用SASS的适当的变量替代解决方案吗?

I found out that LESS has what they call "lazy loading" (http://lesscss.org/features/#variables-feature-lazy-loading), where the last definition of a variable is used everywhere, even before the last definition. I believe this would solve my problem. But does anyone know a proper variable-override solution using SASS?

附录:
这是我已经考虑过的一种技术:以相反的顺序包含文件,对所有变量使用!default(在

ADDENDUM:
Here's one technique I've already thought through: include the files in reverse order, using !default for all variables (this technique was also suggested in the answer to this question). So here's how this would play out:

_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)

因此,该解决方案几乎是 完美. 但是 ,现在,在我的覆盖文件中,我无权访问Bootstrap的_variables.scss中定义的变量,如果要定义变量覆盖,则需要使用该变量(或我自己的其他自定义变量)使用其他Bootstrap变量.例如,我可能想做:$custom-var: $grid-gutter-width / 2;

So that solution is almost perfect. However, now in my override files, I don't have access to variables defined in Bootstrap's _variables.scss, which I would need if I wanted to define my variable overrides (or my own additional custom variables) using other Bootstrap variables. For example, I might want to do: $custom-var: $grid-gutter-width / 2;

推荐答案

已解决,但我不知道它从哪个版本开始工作.我相信该解决方案可能一直可用.经过测试:

Solved, but I don’t know from which version this works. I believe the solution could have always been available. Tested on:

> sassc --version

sassc: 3.2.1
libsass: 3.2.5
sass2scss: 1.0.3

我们将使用简化的环境,因此文件名与Bootstrap的文件名不匹配.

We are going to use a simplified environment, so filenames do not match with Bootstrap’s.

给出一个我们无法控制的框架(例如,仅安装在Continuous Integration环境中,而在我们的计算机中不可用),该框架以以下方式表示SCSS变量:

Given a framework we do not control (for example installed only on the Continuous Integration environment and not available in our machines) that expresses SCSS variables in the following manner:

// bootstrap/_variables.scss

$brand-primary: #f00 !default;
$brand-warning: #f50 !default;

$link-color: $brand-primary !default;

并在使用变量的同一框架中给定一个文件:

And given a file in that same framework that uses the variables:

// bootstrap/main.scss

a:link, a:visited {
  color: $link-color;
}

挑战在于:

以这种方式将框架包含在您自己的应用程序的SCSS中

Include the framework in your own application’s SCSS in such a way that

  1. 变量在框架中的依赖性 被保留并获得荣誉;
  2. 您可以依赖默认值,但仍然可以更改框架依赖项的结果.
  1. variables’ dependencies in the framework are preserved and honors;
  2. you can depend in on the default values but still be able to change the results on the framework dependencies.

更准确地说:

以某种方式将框架包含在应用程序的SCSS中,无论框架中的值如何,$brand-color始终是$brand-warning的反面.

解决方案

主文件如下所示:

Solution

The main file would look like this:

// application.scss

@import "variables";
@import "bootstrap/variables";
@import "bootstrap/main";

您的变量文件将如下所示:

And your variables file would look like this:

// _variables.scss

%scope {
  @import "bootstrap/variables";

  $brand-primary: invert($brand-warning) !global;
}

结果:

> sassc main.scss

a {
  color: blue; }

说明

%scope部分不是SCSS的魔力,它只是名称为scope的隐藏类,仅可用于以后的@extend扩展.我们只是使用它来创建变量作用域(因此而得名).

Explanation

The %scope part is not something magic of SCSS, it’s simply a hidden class with the name scope, available exclusively for later extensions with @extend. We are using it just to create a variable scope (hence the name).

在范围内,我们@import框架变量.因为此刻每个变量都没有值,所以每个变量都会被创建并分配其!default值.

Inside the scope we @import the framework’s variables. Because at this moment there’s no value for each variable every variable is created and assigned its !default value.

但这是the头.变量不是 global ,而是 local .我们可以访问它们,但它们不会污染全局范围,该范围将在以后用于派生框架内部的变量.

But here’s the gimmick. The variables are not global, but local. We can access them but they are not going to pollute the global scope, the one that will be later used to derive variables inside the framework.

实际上,当我们想要定义变量时,我们希望它们是全局的,实际上我们使用!global关键字来表示SCSS将其存储在全局范围中.

In fact, when we want to define our variables, we want them global, and indeed we use the !global keyword to signal SCSS to store them in the global scope.

有一个主要警告:定义变量时不能使用自己的变量.

这意味着在此文件中

%scope {
  @import "bootstrap/variables";

  $brand-primary: black !global;

  @debug $brand-primary;
}

@debug语句将打印 bootstrap/_variables.scss 中定义的默认值,而不是black.

The @debug statement will print the default value defined in bootstrap/_variables.scss, not black.

将变量分为两部分:

%scope {
  @import "bootstrap/variables";

  $brand-primary: black !global;

  @debug $brand-primary;
}

@debug $brand-primary;

第二个@debug确实可以正确打印black.

The second @debug will indeed correctly print black.

这篇关于Bootstrap SASS变量覆盖挑战的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆