我并不介意你是否立即阅读本文,如果你把它加入收藏夹,并且在大脑中留有印象会更好。接下来我讲要谈论一下利用Sass的特性编写个性化样式的话题。
假设你要一次性为不同的品牌做几个不同的网站。假定有四个品牌:
- Bob's Burgers
- Paddy's Pub
- Stu's Stews
- Jurrasic Fork
如果我们为每个品牌,从头到尾地编写页面和样式,那工作量就太大了。大体上看就会有四倍工作量要做——没人有这时间。
每一个品牌的网站都需要独具一格的设计,但是我们可以对所有的品牌使用同一套页面标记。品牌之间也可以有通用布局和内容结构,所以我们也可以重用所有的样式。在所有通用设计的基础上,我们可以添加一层各个品牌独有的样式,从而在不同主题间体现唯一性。Theme Rules in SMACSS介绍了怎样用普通的CSS完成这一系列工作。你需要认清“通用设计”和“个性化设计”之间的区别。通用设计使用通用样式表,个性化设计使用主题特有的样式表。其次,主题特有的样式表要表现在通用样式表上层,最后就可以合力展现不同的主题风格了。
这就完成工作了,但就像是SMACSS的其余部分一样,这只是一个例子,并不意味着要一字不差地遵守。我们可以取其精华(比如通用设计和个性化设计分离的思想),并重新思考符合项目的实现方式。那是要怎样呢?
实现
重中之重:实现应该是适合用户的。我们不希望用户下载可能用不到的样式表。同理,用户应该只需要对样式表请求一次。如有可能,我们应该避免为获取基本样式表发送依次请求之后,在此基础上再次发送请求获取品牌独有的样式。
其次:实现应该是不刁难开发者的。开发者不应该花费时间,去管理散布在各个文件和目录中相似的代码块。说起来也很好解决。所有的代码应该包含在模块中。这减少了开发者理清整个项目结构的压力。这也有助于改善CSS文件间错综复杂的相互依赖关系。这样做不仅对新手方便,也方便了未来的你。
Sass能够优雅地管理这样的工作。我们只需使用一点预处理器组织样式的方式,就可以为多个主题管理,并提高代码的可读性和可维护性。
首先为每个品牌创建一个基础的SCSS文件。
bobs-burgers.scss
paddys-pub.scss
stus-stews.scss
jurassic-fork.scss
注意,这些并不是部件。它们没有以下划线开头,并且都会渲染到各自的CSS文件中。每个品牌只有一个CSS文件。这意味着每个品牌只发送一个请求,页面会更快地展现给用户,也意味着用户会很开心。用户满意就是最好的结果。
在每个文件中,我们都会定义一个$brand
变量,然后引入其他组件。$brand
变量是整个设计技巧的关键。我们就是通过它来输出各个品牌独有的设计代码。
这就是bobs-burgers.scss
:
// Set a variable containing current brand
$brand: 'bobs-burgers';
// Import all components
@import 'header';
@import 'hero';
@import 'footer';
所有品牌的文件看起来都一样,只有$brand
的值是不同的。
等一下,“完全相同”?看上去是复制品!让我们消除它。我们可以把导入列表移到各自文件的底部。这样我们编写一个单一的文件就可以更新所有品牌的样式。我们可以创建一个_manifest. scss
文件(因为这个文件并不单独存在,所以文件名开头由下划线)。现在我们可以将_manifest. scss
导入到所有品牌的文件中,从而消除重复。
这就是新文件,去除了重复的bobs-burgers.scss
:
// Set a variable containing current brand
$brand: 'bobs-burgers';
// Import all components
@import 'manifest';
这是_manifest.scss
:
@import 'header';
@import 'hero';
@import 'footer';
现在开始,我们为不同的品牌创建样式。因为所有品牌的base文件都设置了$brand
变量,我们就可以通过检查该变量的值,为各个品牌编写代码。
如果我们想为每个品牌设置不同的背景颜色,那么在_hero. scss
文件中:
.hero {
// First, styles that all brands
// have in common.
// (The "shared stuff")
font-size: 2em;
font-weight: bold;
border: 1px solid;
// Next, brand-specific styles.
// (The "themed stuff")
@if $brand == 'bobs-burgers' {
border-color: yellow;
}
@if $brand == 'paddys-pub' {
border-color: green;
}
@if $brand == 'stus-stews' {
border-color: blue;
}
@if $brand == 'jurassic-fork' {
border-color: brown;
}
}
编译之后,一个既定品牌样式表就会包含所需的样式:所有品牌通用的样式,以及为该品牌独享的样式。不多也不少。在执行渲染的CSS中,没有一条重写的规则。只有恰到好处,简洁的品牌样式。
在模块中使用各个品牌的条件语句,可以帮助你减少输出结果的混淆。无需查找散布各个文件甚至是子文件中的规则。一切都恰到好处。这使得编写新品牌的代码更容易,也让旧代码更容易理解。
混合宏的便捷
那些@if
语句看起来有几分难看,而且每个品牌都需要编写大串样式。我永远也记不住你是否需要将值用引号包裹起来。
把每个条件放入自己的混合宏中,我们就可以解决一切。这需要为每个品牌编写一个混合宏。
@mixin bobs-burgers {
@if $brand == 'bobs-burgers' {
@content;
}
}
@mixin paddys-pub {
@if $brand == 'paddys-pub' {
@content;
}
}
@mixin stus-stews {
@if $brand == 'stus-stews' {
@content;
}
}
@mixin jurassic-fork {
@if $brand == 'jurassic-fork' {
@content;
}
}
通过这些混合宏,_hero. scss
可以缩减到这样:
. hero {
// First, styles that all brands
// have in common.
// (The "shared stuff")
font-size: 2em;
font-weight: bold;
border: 1px solid;
// Next, brand-specific styles.
// (The "themed stuff")
@include bobs-burgers {
border-color: yellow;
}
@include paddys-pub {
border-color: green;
}
@include stus-stews {
border-color: blue;
}
@include jurassic-fork {
border-color: brown;
}
}
你看:我们从同一个源,得到了四个不同的主题文件。这些品牌样式对于开发者是易于审查和管理的。对于用户没有浪费一次下载和请求。人人都是赢家。
不仅仅是区分颜色,这个技巧还可以让我们有更多发挥的空间。让我们进一步推进:
. hero {
// First, styles that all brands
// have in common.
// (The "shared stuff")
font-size: 2em;
font-weight: bold;
border: 1px solid;
// Next, brand-specific styles.
// (The "themed stuff")
@include bobs-burgers {
border-color: yellow;
}
@include paddys-pub {
border-color: green;
background: url(/images/shamrock.png);
}
@include stus-stews {
border-color: blue;
&:hover,
&:focus {
// You can nest styles and even reference
// the parent from within this mixin!
background-color: blue;
}
}
@include jurassic-fork {
border-color: brown;
background: url(/images/dinosaur-footprints.png);
}
}
你可以尽自己喜欢的改变它。因为这些混合宏实质上是条件式的语法,你甚至可以嵌套额外的选择器或是父选择器。以这种方式使用主题混合宏,最终就会自然而然地变成工作流中的一部分。并且这个技巧远不止使用在定制个性化品牌主题上。我们为Structuring And Serving Styles For Older Browsers使用相同的技巧——改变变量并引入设计。你尽可以做一些奇怪的操作,比如输出一个内联样式表风格指南的样式表。去尝试吧。
警告
最大的警告是编译时间。因为要为每个主题构建一个完整的CSS文件,所以要花费更多时间编译样式。如果这对你来说是个问题,那么你可以试试libsass。它编译Sass比Ruby编译器更快,可能对你有所帮助。
另外,我写这篇文章的前提是假设合并所有的CSS比隔离主题更好。如果用户经常在品牌间切换,或者你的主题文件非常小,那么这就有些不合适了。思考下怎样适合你的项目,然后就做吧。
本文根据@ETHAN MULLER的《Themed Styles With Sass》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://seesparkbox.com/foundry/themed_styles_with_sass。
如需转载,烦请注明出处:http://www.w3cplus.com/preprocessor/themed-styles-with-sass.html