使用 Sass 进行主题化:SCSS 教程
已发表: 2022-03-11使用 Sass 进行样式表开发,即使使用其最基本的功能,如嵌套属性或变量,也可以节省宝贵的时间,并使前端开发人员的工作更轻松。 毫不奇怪,CSS 预处理器已被广泛用作为网站和应用程序创建样式的实际方式。 我们简直不能没有他们了。
谈到主题; 也就是说,在保持网站布局的同时改变网站的外观和感觉,Sass 的特性——比如 mixins 或函数——感觉就像坐飞机而不是走路! 在本 SCSS 教程中,我们将创建一个最小主题并使用 SCSS 为我们的 CSS 编程提供一些超能力。
一个基本的 Mixin 方法
假设我们有以下布局:
<body class="theme-1"> <div class="container"> <div class="left"> Left </div> <div class="right"> Right <button class="button">Button</button> </div> </div> </body> </html>
我们被要求为其创建多个主题。 主题必须更改所有容器(包括主容器)和按钮的颜色,主题将由主体中的类确定,或者它也可以是“外部”容器:
<body class="theme-1">
让我们构建一个名为“themable”的mixin,它将包含我们的配色方案作为参数。
@mixin themable($theme-name, $container-bg, $left-bg, $right-bg, $innertext, $button-bg) { .#{$theme-name} { .container { background-color: $container-bg; border: 1px solid #000; display: flex; height: 500px; justify-content: space-between; margin: 0 auto; padding: 1em; width: 50%; * { color: $innertext; font-size: 2rem; } .left { background-color: $left-bg; height: 100%; width: 69%; } .right { background-color: $right-bg; height: 100%; position: relative; width: 29%; } .button { background-color: $button-bg; border: 0; border-radius: 10px; bottom: 10px; cursor: pointer; font-size: 1rem; font-weight: bold; padding: 1em 2em; position: absolute; right: 10px; } } } }
然后用它来生成我们的主题:
@include themable(theme-1, #f7eb80, #497265, #82aa91, #fff, #bc6a49); @include themable(theme-2, #e4ada7, #d88880, #cc6359, #fff, #481b16);
至此,我们已经节省了很多时间,但是这种方式存在一些问题:
除了颜色之外,主题通常还有很多不同的属性。 例如,如果我们想修改 Bootstrap 主题,那么按照之前的“配方”编写一个 mixin 将难以维护,代码也难以阅读。 另外,我们并没有真正遵循 Sass 最佳实践——例如,将十六进制颜色代码直接输入到 mixin 中。
使用 Sass Map 设计样式方案
借助主要类似于键索引数组的地图,我们可以为我们的主题构建更语义化、更有意义的样式集,这将更容易被我们的同事开发人员维护和理解。 我们也可以使用列表,但就我个人而言,我发现地图更适合此目的。 列表没有键,而键是不言自明的。
我们新方法的映射将是一个嵌套映射:
$theme-1: ( container: ( bg: #e4ada7, color: #000, border-color: #000 ), left: ( bg: #d88880, color: #fff, height: 100%, width: 69% ), right: ( bg: #cc6359, color: #fff, height: 100%, width: 29% ), button: ( bg: #481b16, color: #fff ) );
如果我们想访问我们的方案theme-1
及其子映射的每个部分,我们使用@each
指令来循环它们中的每一个:

@each $section, $map in $theme-1
$section
将返回当前部分的键, $map
将返回与该键对应的嵌套映射。
然后,我们可以使用map-get
函数访问每个地图的属性,比如背景(bg)属性:
map-get($map, bg)
最后,结合我们的新 mixin,基于我们的地图结构,我们可以创建任意数量的主题:
@mixin themable($theme-name, $theme-map) { .#{$theme-name} { .container { .left, .right { font-size: 2rem; } } .container .right { position: relative } .button { border: 0; border-radius: 10px; bottom: 10px; cursor: pointer; font-size: 1rem; font-weight: bold; padding: 1em 2em; position: absolute; right: 10px; } // Loop through each of the keys (sections) @each $section, $map in $theme-map { @if ($section == container) { .container { background-color: map-get($map, bg); border: 1px solid map-get($map, border-color); display: flex; height: 500px; justify-content: space-between; margin: 0 auto; padding: 1em; width: 50%; } } @else { .#{$section} { background-color: map-get($map, bg); color: map-get($map, color); @if ($section != button) { height: map-get($map, height); width: map-get($map, width); } } } } } } @include themable(theme-1, $theme-1); @include themable(theme-2, $theme-2); … …
请注意,我们还使用@if
指令来区分非按钮部分的属性。
@if ($section != button) { height: map-get($map, height); width: map-get($map, width); }
这样,我们可以为某些部分添加不同的属性以创建特定的属性甚至规则,或者我们可以区分具有单个值的键和具有嵌套映射的另一个键。
我们的主题还可以由多个混入使用的许多映射组成,应用于样式表的不同部分。 这完全取决于我们基本布局的复杂性,当然还有我们个人的方法。
进一步优化
Sass 提供了有用的内置函数来为我们节省更多的工作; 例如,hsl 函数如lighten
或darken
来计算,例如,悬停在按钮上时按钮的颜色。
我们可以修改按钮代码以在悬停时使其背景变亮,而不考虑原始背景颜色。 这样,我们不必为此状态添加另一种颜色。
@if ($section != button) { height: map-get($map, height); width: map-get($map, width); } @else { &:hover { background-color: lighten(map-get($map, bg), 20%); } }
此外,通过使用 Sass 模块,我们的代码可以更加清晰和可扩展; 每个主题图都可以包含在一个模块中,然后导入到我们的主样式表中。
@import 'theme-1'; @import 'theme-2'; @import 'theme-3'; … … @mixin themable($theme-name, $theme-map) { .#{$theme-name} { .container { … …
这将要求将模块放置在项目中,如下所示:
/ ├── _theme-1.scss ├── _theme-2.scss └── _theme-2.scss
如果您有兴趣了解有关使用 Sass 干燥 CSS 的更多信息,Toptaler Justin Brazeau 和 Sass 爱好者在他的精彩文章Sass Mixins: Keep Your Stylesheets DRY中讨论了这一点。