# 掌握 SASS 之精华—— @mixin、 @extend 和 Placeholder Selectors最近使用 Rails 折腾小项目,CSS 框架选用了 [Bourbon](https://github.com/thoughtbot/bourbon) 并结合了 [bitters](https://github.com/thoughtbot/bitters) 发现其能很好地利用了 SASS 特性。轻量级且定制性强,相比 bootstrap,Semantic-ui 这类啥都封装好的框架,轻量级多得多。在使用的过程中感叹在 Web 项目一开始的时候就得良好地组织好前端代码,不然地话,在模板文件中到处都是一堆 CSS ,后来者无力去改变也只能是继续堆砌 CSS,毫无阅读性以及组织结构规范,导致了大量的重复样式代码,CSS 复用性不高,作为一名代码癖的程序员,你还能忍受吗?还有一点就是开发者随便改动一个元素的class 或者 id 的样式,在没有良好组织样式代码的前提下很容易导致不可控的样式改变,等到线上更新了才他妈意识到这个class对另外一个元素的样式也改了。接下来看看一个使用了 bitters 组织的 Rails 项目样式代码的组织。- stylesheets - base - extends - _button.scss - _clearfix.scss - mixins - _flash.scss - _bases.scss - _buttons.scss - _forms - _lists.scss - ... - _variables.scss - _account.scss - _users.scss - ... - application.css.scss看到这样的目录结构,有没有很 SASS 味? _bases.scss 文件中 **@import** 了 base 目录下包含了整个样式公共的一些文件,也许你也看到了 **extends** 和 **mixins** 子目录,别着急先上饭前菜,这篇文章重要就是要说明它们。_variables.scss 内容只要是颜色值、链接样式、字体样式等一些变量,例如```$black: #000000;```极其方便地被引用和复用。base 文件夹下的其他文件都是各种 HTML 元素的样式,有人说,你用 Semantic-ui 多方便啊,为啥这么折腾,哈,这不是我们今天讨论的内容;然后就是base 文件夹以外的一些样式文件都是按照其业务逻辑来组织,各个样式文件各司其职多好! ##### ~~以上就是饭前菜,同是我也是分割线,请忽略,下面的内容才是重点~~ ### 关于 Mixin在 SASS 的世界里 ```mixin``` 是一种指令。它可以像函数一样把多个样式组织成为“一块”方便引用及复用,当然这个函数也是可以传递参数的。举个栗子:```@mixin center() { display: block; margin-left: auto; margin-right: auto;}.container { @include center(); /* Other styles here... */}/* Other styles... */.image-cover { @include center;}```> center 没有参数,你可以省略括号,但还是最好不要省哈。通过 mixin ,在需要居中的元素上没必要都重复写三行代码,仅仅是简单地 ```@include``` 就好了,可方便简单了。 还可以传参呢?再看个栗子。```@mixin size($width, $height: $width) { width: $width; height: $height;}```要在其他元素上引用这样的大小样式:```.icon { @include size(32px);}.cover { @include size(100%, 10em);}```### 关于 Placeholder在 SASS 的世界里,Placeholder 也是一种特别的元素选择器,没错,就是类似 class 或者 id ,但有其特别之处。 placeholder 用 **%** 百分号表示。作为一种元素选择器,意味着能够被 SASS 中的 **@extend** 指令引用。先看栗子```%center { display: block; margin-left: auto; margin-right: auto;}```细心的你一眼就看出这个栗子和上文的 mixin 没多大的区别,就是把 ```@mixin``` 替换为 ```%```而已,那么它们有啥区别呢,别急等会讲。此时你只记住这句话就好了:**在没有使用之前,placeholder编译不会CSS代码**。 在使用 placeholder 之前,我们简单介绍一下 ```@extend``` :该指令用于从 CSS 选择器以及 placeholder 这个特殊的选择器继承样式属性。那么使用 placeholder 就是这样:```.container { @extend %center;}```### 选用 mixin 还是 placeholder上文抛出了 mixin 和 placeholder 有什么区别的问题,那么我们应该用哪种呢?是时候给出答案了。 使用 mixin 还是 placeholder 取决于使用上下文。具体一点就是:如果是需要传参数,建议使用 mixin ,否则使用 placeholder ,给出两个理由:1. placeholder 不支持传参啊。2. sass 编译之后,使用的 mixin 会生成大量重复代码,导致最后的样式文件体积变大。而 placeholder避免了生成重复代码。请看两者编译后的对比栗子。 ``` @mixin center { display: block; margin-left: auto; margin-right: auto; } .container { @include center; } .image-cover { @include center; } ``` 编译后 ``` .container { display: block; margin-left: auto; margin-right: auto; } .image-cover { display: block; margin-left: auto; margin-right: auto; } ``` ``` %center { display: block; margin-left: auto; margin-right: auto; } .container { @extend %center; } .image-cover { @extend %center; } ``` 编译后 ``` .container, .image-cover { display: block; margin-left: auto; margin-right: auto; } ```看出来了吧,看不出来我也不解释了,哼。 来,看一下 mixin 和 placeholder 混合使用进阶版栗子```%center { margin-left: auto; margin-right: auto; display: block;}@mixin skin($color, $size) { @extend %center; background: $color; height: $size;}a { @include skin(pink, 10em) }b { @include skin(blue, 90px) }```我们可以看出 a,b 都想内容居中,但是颜色和大小需要自定义。充分地体现了 **传参就用mixin,其他的用 placeholder 的思想**,编译之后产生的CSS如下:```a, b { margin-left: auto; margin-right: auto; display: block;}a { background: pink; height: 10em;}b { background: blue; height: 90px;}```### 关于 @extend还没写完参考链接: [Sass: Mixin or Placeholder?](http://www.sitepoint.com/sass-mixin-placeholder/) [What Nobody Told You About Sass’s @extend](http://www.sitepoint.com/sass-extend-nobody-told-you/) [Why You Should Avoid Sass @extend](http://www.sitepoint.com/avoid-sass-extend/)