如何使用 Sass 和 SMACSS 维护 CSS
我们一直以来都是 SMACSS 的忠实粉丝,然而一个纯 SMACSS 方法最适合于一个全新的项目中的普通CSS。我们的市场网站,我们使用了Sass编写样式,而且里面还有好几年的CSS遗留物。
我们最近在精减我们的CSS,让我们的团队更方便的维护,而在精减过程中,我们团队并没有扔掉我们现有的样式或者从零开始。
我们基于SMACSS方法着手解决SMACSS和 OOCSS 的问题,但从 BEM 和 Toadstool 我们也有一些修改和一些想法。
注意:你将需要对 SMACSS 有点了解,如果你不了解,可以点击 这里。
SMACSS 的呈现
SMACSS 定义了五种样式类型:
- Base (基本)
- Layout(布局)
- Module (模块)
- State (状态)
- Theme (皮肤)
我们的方法看起来像这样:
- Base (基本)
Layout(布局)- Module(模块)
- State(状态)
Theme(皮肤)
Base 基本
在新项目中我们的基本样式仅仅使用了Normalize,用来重置元素的基本样式(颜色、排版、外距和内距等)。
不幸的是,在线上的基本CSS来自一个时间相当久的CSS重置,里面有一些默认字体样式几乎都覆盖了。多年来,这些样式都放置在顶部,难以改变不影响其他所有的样式。
即使有这些缺点,我们仍然可以修改我们的基本样式,就像SMACSS的基本样式。
Layout 布局
在我们的方法中不是基本样式和全局的类名而是模块。
SAMCSS规划了主要布局组件(如,页头header
,侧栏sidebar
,网格grid
等等)和其他的一切。我们发现这种区别有几个不必要的因素:
- 模块通常用展示他们的子组件,同样的方式主要的组件展示在页面上。
- 即使我们100%确定组件将永过不会被重用,因此和可重用的组件相比没有任何好处。
布局和模块之间的界线太模糊了,布局做为一种特殊的类别保留下来是很价值的。
Module 模块
模块是独立的,可重用的组件,哪怕是不知道它们的父容器。他们唯一的依赖关系是应用基本样式。当它不在需要时,我们可以安全的删除模块,而不什么影响我们的CSS。
BEM双下划线语法用于一个模块的子组件 范围 中,我们使用CSS子选择器随意 适合深度的适用性。
BEM双连字符语法作为修饰符来表示子类,或和关键字is-
、模块的具体状态相结合。
因为设置模块的宽度width
,定位position
,外距margin
都需要上下文出现的相关因素,我们的模块要么是全屏的块元素要么是内联元素。
这里有一个示例(modules/_my_module.scss
):
.my-module {
background-color: maroon;
position: relative;
> a {
color: aqua;
}
}
.my-module--important {
@extend .my-module;
border: 3px solid fuchsia;
}
.my-module--is-active {
background-color:red;
}
.my-module__close-button {
position: absolute;
right: 0;
top: 0;
}
当我第一次开始写模块就像这样,我最终使用很复杂的类来定义模块的名字:.my-module__child-component__grandchild-component--modifier
。
但除了position
和尺寸相关属性外,大多数子组件可以提取出自己独立的模块。所以如果你离开定位到父元素,我们可以设置为三个小的、独立的模块。
modules/_my_module.scss:
.my-module {
//...
}
.my-module__child-component {
width: 100px;
}
modules/_child_component.scss:
.child-component {
//...
}
.child-component__grandchild-component {
position: absolute;
top: 10px;
}
modules/_grandchild-component.scss:
.grandchild-component {
//...
}
.grandchild-component--modifier {
//...
}
example.html:
<div class="my-module">
<div class="my-module__child-component">
<div class="child-component">
<div class="child-component__grandchild-component">
<div class="grandchild-component--modifier"></div>
</div>
</div>
</div>
</div>
.grandchild-component
和.child-component
独立于他们的父容器。这个模块是用于他的子容器定位。这样做好处是嵌套的UI组件彼此完全脱离。
State 状态
模块的具体状态作为模块的本身被定义在相同的文件中(如上面的.my-module--is-active
),但我们要保持全局状态类的分离,如.is-hidden
。
Theme 皮肤
我们为各个模板市场写theme
(如ThemeForest和GraphicRiver制作各作皮肤),但我们通过在一个配置文件中设置变量的设置来实现站点的特定风格。
Sass 将一切整合
Configuration 配置
application.scss
第一个导入的样式文件就是_config.scss
。在这里,我们设置了全局变量,共同使用。这里包括颜色、字体大小、字体、响应式断点等等。
我们还包括市场特定的配置文件,用来设置为每个市场的配色文案的变量。
Mixins 混合
所有的Mixin保存在自己的文件中并放置在一个叫mixins
的目录中,和全局都可以使用。我们也导入了处理浏览器供应商前缀的Mixin库,如Compass的Sprites图和供应商前缀。
Grid 网格
我们的网格框架只是一个模块。
我们避开在HTML中使用类似于span-5
这样的网格类名,相反使用 Susy 这种基于列宽而又独立于模块的类名。
modules/_page.scss:
.page {
//...
}
.page__sidebar {
@include span-columns(3,12);
}
.page__content {
@include span-columns(9 omega,12);
}
在模块中 .grid
只是包含所有东西,他只是Susy网格容器。
Internet Explorer
我们仍然支持IE7和IE8。我们过去使用HTML5 Boilerplate方法来处理那些浏览器兼容,但这意味着我们要使用很多.lt-ie8
这样的类名来处理兼容。
现在我们使用 这样的技巧 来为那些浏览器生成独立的application-ie8.css
和application-ie7.css
样式。
IE指定的样式就写在模块中。
modules/_my_module.scss:
.my-module {
color: chartreuse;
@if $ie7 {
position: relative;
zoom:1;
}
}
给好的浏览器提供了一个简洁的application.css
,里面没用任何IE垃圾代码,相反老IE用户会得到他们自己的特殊版本。
我们不能做什么
我们不追求可读的CSS输出。当你像这样写模块,可以查看类名和直接选择正确的Sass文件而不是通过开发者工具试图找出一个特定的样式。Source Maps也一样。
我们不打算从我们编译的CSS中删除每一个重复点。我们想要开发尽可能的容易,而又不影响性能。到目前为止用mixins模块代替@extend
,这样并不会增加原始文件大小。
结论
开始几个月,我们将模块的文件放到有点乱的 stylesheets
目录。当我们添加新的特性和转换现有的特性,我们的modules
目录下的样式文件只增不减。
来自 ThemeForest 的主要样式文件 application.scss
,现在看起来像这样:
// Config
@import config_global;
@import config_themeforest;
// Vendor mixin libraries
@import compass;
@import susy;
// Our mixins
@import mixins/**/*;
// Old crud. Our base styles, plus everything else that will eventually
// be converted into modules.
@import old_stuff/**/*;
// Modules
@import modules/**/*;
// Global state classes
@import state;
我们可以成功的实现现代化的 CSS 架构,而没有仍掉我们现有的样式或从零开始。
扩展阅读
- 对于这个方法,样式 主要参考于starter项目,尝试一下,让我们知道您的想法
- 如果你从未了解过SMACSS,你可以到 smacss.com了解更多的相关介绍
- Harry Roberts有一系列文章关于介绍可伸缩的CSS。从 BEM语法介绍 开始和工作方式介绍
- Nicolas Gallagher 在这个方面也有很多优秀的分享,关于HTML语义和前端架构一文就是一个很好的思想概述,让我们受益不浅。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论