我使用Laravel Mix和Webpack进行SASS预处理。
我有两个"主题"在我想要精益求精的网站上,继承他们需要的变量。例如,我的主要主题将按此顺序包含:
// Primary theme
@import "./primary-variables.scss";
@import "/path/to/default/theme/main.scss";
我的默认主题如下:
// Default theme
@import "./default-variables.scss";
@import "~bootstrap-sass/assets/stylesheets/_bootstrap";
与this question类似,我首先包含主要变量,然后是默认主题变量,然后是最后一次引导。
在我的默认主题中,我将!default
添加到所有变量中,因此在重新定义Bootstrap时,它们将在优先级中使用,而在新的情况下,它们将成为默认值。主要主题根本不使用!default
。
如果Bootstrap将$brand-danger
定义为red !default
,我的默认主题会将其重新定义为blue !default
,我的主要主题将其重新定义为yellow
,我的渲染输出将为黄色 - 太棒了!
当我需要引用仅在我的主要主题的其他级别定义的变量时。例如:
// Primary theme:
// This fails since I haven't defined $brand-primary in my primary theme
$my-primary-theme-variable: $brand-primary;
现在,构建失败并显示错误primary-theme/src/scss/main.scss doesn't export content
。
我可以通过将整个Bootstrap变量文件复制到我的主要主题并根据需要更改变量来解决此问题,但我并不是真的想要这样做。
SASS变量处理器如何实际工作?我是否可以只更改主题中的一个Bootstrap变量而无需重新定义整个文件?
This question非常相似。
答案 0 :(得分:3)
您似乎正在使用 @include 导入您的SCSS尝试使用 @import - 如果这只是问题中的拼写错误,请告诉我们: - )
@import "./primary-variables.scss",
"/path/to/default/theme/main.scss"
;
我在你所指的the question上添加了一些快速笔记。 关于!default 标志的重要一点是,它在选择器中使用时生效,并且不会重新定义变量。
Sass在处理变量时没有向前看 - 它打印出当前值。在这个例子中,.class-1将是 red ,因为重新定义在选择器中使用后出现.class-2将为蓝色,因为没有默认标志。
$brand-color: red !default; // defined
.class-1 { background-color: $brand-color; } // red
$brand-color: blue; // re-defined
.class-2 { background-color: $brand-color; } // blue
默认标志将导致Sass跳过变量重定义。在此示例中,结果将首先定义为 red 。由于默认标志,将忽略以下两个重新定义。
$brand-color: red !default; // defined
$brand-color: blue !default; // ignored
$brand-color: green !default; // ignored
.class-1 { background-color: $brand-color; } // red
在这种情况下,将使用来自配置的所有变量 - 如果未在config中定义,则来自partial-1的变量,而最后的partial-2将定义未在其他两个中定义的任何变量。
@import '_config.scss'; // definition
@import '_partial-1.scss'; // contains defaults
@import '_partial-2.scss'; // contains defaults
希望有道理: - )
// _default-theme.scss
@import '_default-variables.scss', '_bootstrap.scss';
// _primary-theme.scss
// primary variables will override defaults or use defaults if not defined
@import '_primary-variables.scss', '_default-theme.scss';
// style.scss
@import '_primary-theme.scss'; // or '_default-theme.scss'
如果您的默认和主要内容对每个主题都是唯一的,您可以创建一个范围混合来处理编译的内容。
这是一个非常基本的版本:
// _scope.scss
$scope-context: null !default;
@function scope($scopes: null, $true: true, $false: false) {
@each $scope in $scope-context {
@if index($scopes, $scope) { @return $true }
}
@return $false;
}
@mixin scope($scopes: null) {
@if scope($scopes) or length($scopes) == 0 and not $scope-context {
@content;
}
}
工作原理
范围mixin采用上下文参数和内容块 @content 。如果传递的上下文与全局变量($ scope-context)匹配,则内容块将被呈现。
// _default-theme.scss
.class { content: 'Will show in both themes'; }
@include scope(default-theme){
.class { content: 'Will only show in the default theme'; }
}
@include scope(primary-theme){
.class { content: 'Will only show in the primary theme'; }
}
// can also be used as "if" function
.class {
content: scope(default-theme, 'Is default', 'Not default')
}
在您的情况下,在默认变量和主变量中定义$ scope-context
// _default-variables.scss
$scope-context: default-theme !default;
// _primary-variables.scss
$scope-context: primary-theme;
...并将_scope.scss添加到_default-theme.scss
// _default-theme.scss
@import '_default-variables.scss', '_bootstrap.scss', '_scope.scss';
答案 1 :(得分:1)
我发现的问题是我对SASS的工作方式做了错误的假设。
定义变量声明时,它的值在您编写时编译。例如,$my-var: $brand-primary
会在处理$brand-primary
时将{em>当前值分配给$my-var
。
这意味着我无法实现我想要的,包括在Bootstrap顶部包含一个最小变量文件,因为它只会更新变量本身,而不是在Bootstrap中引用该变量的任何其他变量
它并不优雅,但为每个主题复制整个变量文件,并根据需要在每个地方进行调整。