CSS 预处理器是什么?通常来讲,它们基于 CSS 扩展了一套属于本身的 DSL(Domain Specific Language),来解决咱们书写 CSS 时难以解决的问题:css
归结起来就是抽象能力。因此这就决定了 CSS 预处理器的主要目标:提供 CSS 缺失的样式层复用机制、减小冗余代码,提升样式代码的可维护性。这不是锦上添花,而偏偏是雪中送炭。html
可是,CSS 预处理器也不是万金油,CSS 的好处在于简便、随时随地被使用和调试。预编译 CSS 步骤的加入,让咱们开发工做流中多了一个环节,调试也变得更麻烦了。更大的问题在于,预编译很容易形成后代选择器的滥用。因此在使用 CSS 预处理器时,要注意避免出现此类问题。前端
Sass 中变量以 $ 打头比较不容易和 CSS 标准语法冲突。Less 中变量则以 @ 打头,虽然说容易和后续规范更新的新语法冲突,可是理论上只要 CSS 规范不引入 @a: b
这样的规则,问题也不大。并且规范制定的时候也会参考不少现有的实现。git
Sass 和 Less 的变量机制有很大的不一样,Sass 是相似 JS 的块级做用域同样,能够在做用域内从新赋值而不影响外部,Less 是以全局的最后一次赋值为准。SASS 和 SCSS 只是两种语法风格而已,SCSS 更贴近 CSS 语法,前端写起来更舒服。Less 和 Sass 最经常使用的部分并无明显的区别,不用太在乎该用哪一个,Just pick one。至于公司用哪一个,跟着用就行,不出大问题不用考虑换。github
下文复制自 浅谈 CSS 预处理器(一):为何要使用预处理器?,文中的示例代码均采用 Stylus 做为 CSS 预处理语言。编程
页面愈来愈复杂,须要加载的 CSS 文件也愈来愈大,咱们有必要把大文件切分开来,不然难以维护。传统的 CSS 文件切分方案基本上就是 CSS 原生的 @import
指令,或在 HTML 中加载多个 CSS 文件,这些方案一般不能知足性能要求。浏览器
CSS 预处理器扩展了 @import
指令的能力,经过编译环节将切分后的文件从新合并为一个大文件。这一方面解决了大文件不便维护的问题,另外一方面也解决了一堆小文件在加载时的性能问题。bash
把文件切分的思路再向前推动一步,就是“模块化”。一个大的 CSS 文件在合理切分以后,所产生的这些小文件的相互关系应该是一个树形结构。app
树形的根结节通常称做“入口文件”,树形的其它节点通常称做“模块文件”。入口文件一般会依赖多个模块文件,各个模块文件也可能会依赖其它更末端的模块,从而构成整个树形。框架
如下是一个简单的示例:
entry.less
├─ base.less
│ ├─ normalize.less
│ └─ reset.less
├─ layout.less
│ ├─ header.less
│ │ └─ nav.less
│ └─ footer.less
├─ section-foo.less
├─ section-bar.less
└─ ...
复制代码
入口文件 entry.less
在编译时会引入所需的模块,生成 entry.css,而后被页面引用。
若是你用过其它拥有模块机制的编程语言,应该已经深有体会,模块化是一种很是好的代码组织方式,是开发者设计代码结构的重要手段。模块能够很清晰地实现代码的分层、复用和依赖管理,让 CSS 的开发过程也能享受到现代程序开发的便利。
选择符嵌套是文件内部的代码组织方式,它可让一系列相关的规则呈现出层级关系。
在变动出现以前,CSS 中的全部属性值都是“幻数”。你不知道这个值是怎么来的、它的什么样的意义。有了变量以后,咱们就能够给这些“幻数”起个名字了,便于记忆、阅读和理解。
接下来咱们会发现,当某个特定的值在多处用到时,变量就是一种简单而有效的抽象方式,能够把这种重复消灭掉,让你的代码更加 DRY。
变量让开发者更容易实现网站视觉风格的统一,也让“换肤”这样的需求变得更加轻松易行。
光有变量仍是不够的,咱们还须要有运算。若是说变量让值有了意义,那么运算则可让值和值创建关联。有些属性的值其实跟其它属性的值是紧密相关的,CSS 语法没法表达这层关系;而在预处理语言中,咱们能够用变量和表达式来呈现这种关系。
举个例子,咱们须要让一个容器最多只显示三行文字,在之前咱们一般是这样写的:
.wrapper {
overflow-y: hidden;
line-height: 1.5;
max-height: 4.5em; /* = 1.5 x 3 */
}
复制代码
你们能够发现,咱们只能用注释来表达 max-height
的值是怎么来的,并且注释中 3
这样的值也是幻数,还须要进一步解释。将来当行高或行数发生变化的时候,max-height
的值和注释中的算式也须要同步更新,维护起来很不方便。
接下来咱们用预处理语言来改良一下:
.wrapper
$max-lines = 3
$line-height = 1.5
overflow-y: hidden
line-height: $line-height
max-height: unit($line-height * $max-lines, 'em')
复制代码
乍一看,代码行数彷佛变多了,但代码的意图却更加清楚了——不须要任何注释就把整件事情说清楚了。在后期维护时,只要修改那两个变量就能够了。
值得一提的是,这种写法还带来另外一个好处。$line-height
这个变量能够是 .wrapper
本身定义的局部变量(好比上面那段代码),也能够从更上层的做用域获取:
$line-height = 1.5 // 全局统一行高
body
line-height: $line-height
.wrapper
$max-lines = 3
max-height: unit($line-height * $max-lines, 'em')
overflow-y: hidden
复制代码
这意味着 .wrapper
能够向祖先继承行高,而不须要为这个“只显示三行”的需求把本身的行高写死。有了运算,咱们就有能力表达属性与属性之间的关联,它令咱们的代码更加灵活、更加 DRY。
把经常使用的运算操做抽象出来,咱们就获得了函数。
开发者能够自定义函数,预处理器本身也内置了大量的函数。最经常使用的内置函数应该就是颜色的运算函数了吧!有了它们,咱们甚至都不须要打开 Photoshop 来调色,就能够获得某个颜色的同色系变种了。
举个例子,咱们要给一个按钮添加鼠标悬停效果,而最简单的悬停效果就是让按钮的颜色加深一些。咱们写出的 CSS 代码多是这样的:
.button {
background-color: #ff4466;
}
.button:hover {
background-color: #f57900;
}
复制代码
我相信即便是最资深的视觉设计师,也很难分清 #ff4466
和 #f57900
这两种颜色到底有什么关联。而若是咱们的代码是用预处理语言来写的,那事情就直观多了:
.button
$color = #ff9833
background-color: $color
&:hover
background-color: darken($color, 20%)
复制代码
此外,预处理器的函数每每还支持默认参数、具名实参、arguments
对象等高级功能,内部还能够设置条件分支,能够知足复杂的逻辑需求。
Mixin 是 CSS 预处理器提供的又一项实用功能。Mixin 的形态和用法跟函数十分相似——先定义,而后在须要的地方调用,在调用时能够接受参数。它与函数的不一样之处在于,函数用于产生一个值,而 Mixin 的做用是产生一段 CSS 代码。
Mixin 能够产生多条 CSS 规则,也能够只产生一些 CSS 声明。
通常来讲,Mixin 能够把 CSS 文件中相似的代码块抽象出来,并给它一个直观的名字。好比 CSS 框架能够把一些经常使用的代码片段包装为 mixin 备用,在内部按需调用,或暴露给使用者在业务层调用。
举个例子,咱们常常会用到 clearfix 来闭合浮动。在原生 CSS 中,若是要避免 clearfix 代码的重复,每每只能先定义好一个 .clearfix
类,而后在 HTML 中挂载到须要的元素身上:
/* 为 clearfix 定义一个类 */
.clearfix {...}
.clearfix::after {...}
复制代码
<!-- 挂载到这两个元素身上 -->
<div class="info clearfix">...</div>
...
<footer class="clearfix">...</footer>
复制代码
把表现层的实现暴露到告终构层,是否是很不爽?而在预处理器中,咱们还能够选择另外一种重用方式:
// 为 clearfix 定义一个 mixin
clearfix()
...
&::after
...
// 在须要的元素身上调用
.info
clearfix()
footer
clearfix()
复制代码
CSS 预处理语言没法直接运行于浏览器环境,这意味着咱们编写的源码须要编译为 CSS 代码以后才能用于网页。这彷佛是一个门槛,须要咱们付出“额外”的成本。
但在目前的大环境下,大多数项目的前端开发流程已经包含了构建环节,好比选择任何一个脚本模块化方案都是须要在部署时走一道打包程序的。因此对大多数团队来讲,这个门槛其实已经跨过去一大半了。
而一旦接受了这种设定,咱们还能够享受到“额外”的福利。在给 CSS 的开发加入编译环节的同时,还能够顺道加入其它构建环节,好比代码校验、代码压缩、代码后处理等等。
“代码后处理”是指 PostCSS 平台上各种插件所提供的功能,光是 Autoprefixer 这一项就已经值回票价了。咱们不再须要在 CSS 代码中手工添加浏览器前缀了,直接使用标准写法,剩下的事情让工具搞定吧!
本文中大部份内容直接复制整合了参考资料中的内容,由于这些文章写的很好,不必再用本身的话复述,所以取长补短,进行了整合,版权归原做者全部。