记得刚碰见css的时候,咱像是见了美人儿同样,简直是爱不释手啊,简简单单写几行算不上代码的代码,就能作出这么漂亮的东西,这也成了咱前端之路的最初动力。css
然而,随着项目体量和页面复杂度的增长,咱很快就发现这美人儿非但不漂亮,并且缺胳膊少腿儿的:html
.page .content .left-side .profile .name{};
.page .content .left-side .profile .age{};
CSS 没有模块系统,你当我 @import 是空气?
CSS 的 @import 规则是能够在一个 css 文件导入其余 css 文件,但这货须要执行到它时才能触发浏览器去下载它所 import 来的 css 文件,致使页面加载起来特别慢,还不如直接在 里写一大坨
标签的引入效率高,是名副其实的鸡肋功能,演员通常的存在,用你一次算我输。前端
有需求就会有市场,Sass(Syntactically Awesome Style Sheets) 应运而生。程序员
老规矩,先来看看 Sass 官网的原话:编程
Sass 是世界上最成熟、最稳定、最强大的专业级 CSS 扩展语言!浏览器
这货还真是一点也不谦虚,“最成熟,最稳定,最强大”。sass
经过这几年项目中的实际运用,咱发现这句简短霸气的描述其实并无丝毫的浮夸,Sass 的确厉害,彻底能够 hold 住这三个“最”字,实至名归。编程语言
什么是预处理器
预处理器是在程序源文件被编译以前根据预处理指令对程序源文件进行处理的程序。说白了,预处理器只不过是一个文本替换工具而已。CSS 预处理器则是经过将有特殊语法和指令的源代码处理成浏览器可以使用的 CSS 文件的程序。
是 Sass 仍是 SCSS?
SCSS 是 Sass 3 引入的新语法,语法上彻底兼容原生 CSS,功能上彻底继承 Sass,能够说是 CSS 和 Sass 的完美融合。SCSS 之于 Sass 犹如 CSS3 之于 CSS,ES6 之于 JS。因此别纠结,实际上是一个东西啦。ide
接下来就细数 Sass 带给我们的四大实用特性,想必你必定已经使用过它们中的一个或几个。模块化
想一想以前我们是怎样写原生 css 的:
.page .content .left-side .profile .name{ font-size: 2rem; } .page .content .left-side .profile .age{ color: red; }
如今使用 scss 能够这样写:
.page{ .content{ .left-side{ .profile{ .name{ font-size: 2rem; } .age{ color: red; } } } } }
编译后
.page .content .left-side .profile .name{font-size: 2rem;} .page .content .left-side .profile .age{color: red;}
这种嵌套写法的好处是显然的:
变量一直是全部编程语言的标准配置。然而 CSS 就没有,再次证实 CSS 多是一门假语言。好在 Sass 补上了这个短板。
没有变量以前的代码(这里以定义一系列表示成功风格的样式组件为例):
.success-bg{ background: #dff0d8; } .success-panel{ .panel-heading{ background: #dff0d8; } .panel-body{ border: 1px solid #dff0d8; } }
使用了变量后的代码:
$success-color: #dff0d8; .success-bg{ background: $success-color; } .success-panel{ .panel-heading{ background: $success-color; } .panel-body{ border: 1px solid $success-color; } }
使用变量的好处是显而易见的:
模块化是软件工程的第一要务,是大型项目的必需建筑。软件工程的主要目标就是控制复杂度,这也正是模块化的目的。经过将一个大型复杂的工程拆解成一个个的小模块,使得校验、调试、测试都垂手可得。
CSS原生的 @import
提供了一个并无卵用的假模块系统。Sass 对 @import
进行了拓展,实现了一个真正意义上甚至功能更强大的模块系统。Sass 选择对 @import
进行扩展,而不是新建一个指令,可见 import 这个关键字的语义之强,JavaScript 模块系统的关键字也是 import
。
没有模块系统以前:
<!-- index.html --> <link rel="stylesheet" href="/your/site/common.css"> <link rel="stylesheet" href="/your/site/popup.css"> <link rel="stylesheet" href="/your/site/module_a.css"> <link rel="stylesheet" href="/your/site/site.css">
有了模块系统以后:
/* site.scss */ @import "common"; @import "popup"; @import "module_a";
<!-- index.html --> <link rel="stylesheet" href="/your/site/site.css">
好处嘛天然不用多说了:
混合(mixin)特别相似于 JavaScript 中的函数,然而 Sass 提供了用于表达式计算的 @function
函数指令,这里就很差这么类比了。但其实就是这么个东西,调用的时候会返回一段样式。
好比下面一段存在重复样式的代码。
复用以前:
.description{ color: red; border: 1px solid #e3e3e3; border-radius: 2px; } .article{ color: #444; border: 1px solid #e3e3e3; border-radius: 2px; }
稍做优化:
.description, .article{ border: 1px solid #e3e3e3; border-radius: 2px; } .description{ color: red; } .article{ color: #444; }
彷佛不错,可是以后再新加相似样式时,
.description, .article, .style01, .style02{ border: 1px solid #e3e3e3; border-radius: 2px; } . . . .style01{} .style02{}
每次都要改两个地方,很麻烦,很容易漏,尤为是将通用样式分离出来的话更容易出错。
再作优化:
.grey-border-radius{ border: 1px solid #e3e3e3; border-radius: 2px; } .description{ color: red; } .article{ color: #444; }
彷佛好了一点,但这样的话,html 每一个使用的标签都须要多加上一个 .grey-border-radius 类。很显然这是多余的。这种作法能够说是“凑合”。
使用 Sass 复用以后:
@mixin grey-border-radius{ border: 1px solid #e3e3e3; border-radius: 2px; } .description{ @include grey-border-radius; color: red; } .article{ @include grey-border-radius; color: #444; }
编译后的 css 输出:
.description { border: 1px solid #e3e3e3; border-radius: 2px; color: red; } .article { border: 1px solid #e3e3e3; border-radius: 2px; color: #444; }
看到了吧,这种作法简直“完美”:
若是熟练合理地运用上面的四大特性,你已是CSS代码工程化方面的砖家了,所写出来的代码必是清晰易维护的。Sass 提供了更多的功能,但对普通开发者来说,上面的四点只要使用熟练,已经彻底够用了,其余的可看可不看。下面提供的功能但愿你们慎用,有的是出于性能考虑,有的则是从开发维护的角度考虑。尤为不要为了秀技术而去使用它们,过犹不及,事缓则圆,此为中庸之道。
继承是面向对象程序设计的三大特性之一,这也是为何说它是语义层复用的缘由。你能够说一个错误信息框继承了一个信息框,而不能说一个错误信息框继承了一个灰色圆角,虽然也是能够强行这么说,但不免有些别扭哈哈。
好比说下面定义一组信息框的样式,包括默认,成功和错误的样式。
使用继承以前:
.msg{ border: 1px solid #e3e3e3; background: #dff0d8; } .msg-success{ color: #4cae4c; } .msg-error{ color: #d43f3a; }
一样是上面说到的问题,编写 html 时每一个使用的标签都须要多加上一个 .msg 类,不少余。
使用继承以后:
.msg{ border: 1px solid #e3e3e3; background: #dff0d8; } .msg-success{ @extend .msg; color: #4cae4c; } .msg-error{ @extend .msg; color: #d43f3a; }
编译后
.msg, .msg-success, .msg-error { border: 1px solid #e3e3e3; background: #dff0d8; } .msg-success { color: #4cae4c; } .msg-error { color: #d43f3a; }
能够看出,上面的效果使用混合(mixin)也能够完成。但不一样的是:继承拷贝的是选择器,而混合(mixin)拷贝的是样式片断。
使用混合(mixin)仍是继承(extend)?
你确定觉得既然继承拷贝的是选择器,而混合拷贝的是大段的样式,那固然是优先选择继承了。然而偏偏相反,推荐作法是 尽量使用混合(mixin),具体缘由 戳这里。
这个功能主要用于值的计算,和 JavaScript 中的函数相似。
好比移动端开发时能够封装成一个函数用于把 px 转成 rem。
$baseFontSize: 20; @function px2rem($val) { @return $val/$baseFontSize + rem; } .big-text{ font-size: px2rem(30); }
编译后:
.big-text { font-size: 1.5rem; }
这样在拿到设计MM给的视觉稿以后就能够直接使用 px 进行测量使用了。
控制流即程序语言中的 if/else
,for
,while
等控制语句。Sass 一样提供了指令实现:
@if
@for
@each
@while
它们一般配合 @function
指令使用,然而功能虽强,却不经常使用到。毕竟样式表的功用主要是描述页面样式,而不是提供更多控制。所以在这里不展开研究,感性趣的 戳这里。
Sass 完美弥补了上面原生 CSS 暴露的几个短板,同时新语法 SCSS 使 CSS 开发者能够无缝过渡,是 CSS 预处理器中当之无愧的佼佼者。使用 Sass 容易编写出结构清晰,可复用,易维护的工程样式文件,这正是工程化的指望。这么好的东西,速速用起来。
本文主要参考了 Sass 中文网。