## 如何搭建移动端CSS样式库

### 为什么需要搭建自己的样式库
现在这么多优秀的开源组件库,为什么还要搭建自己的组件库呢?
<br />每个公司都有自己的设计风格,以及不一样的产品需求,如果引入其他第三方组件，很大可能带来风格和操作上的不统一。
<br />大部分情况下,无法直接使用开源组件库。开发人员接到页面需求后需从头开始进行页面布局。
<br />开发自己的样式库可以做到以下几点:
1. 设计风格统一,可以根据自己的产品进行深度定制
2. 统一维护,组件样式复用,减少样式兼容Bug,提高开发效率
3. 统一规范,防止多人协作时候风格冲突样式冲突,提高页面可读性和可维护性
4. 提高前端与设计交互的协作效率

### 前期准备
搭建样式库之前,需要做哪些准备?
1. 确定模块分类方法
2. 确定命名规范和行为规范
3. 确定字体、字体大小、主次色调、主次间距、页面层级规范等
4. 确定工程的组织结构,如何便于开发维护与发布
5. 确定说明文档的输出方式

### 工程的组织结构
工程的组织结构要需便于开发、维护与发布
<br />**文件组织结构**: 见[工程](https://github.com/qiuguorong/bxui)
<br />**开发**: 使用LESS + Vue(DEMO) + Webpack + Postcss
<br />**DEMO与文档**: 使用Github + GitPages + GitBook,以后会维护到公司的Gitlab上。
<br />**发布**: 目前一键发布到私有npm,并同步上传到CDN

### CSS模块分类方法
大部分以组件为粒度进行分类,小部分以属性为粒度进行分类.<br/>
组件内部更多的以属性为粒度进行分类<br/>
将REM和OOCSS两种设计模式结合使用<br>
可参考[Mint UI Button](http://elemefe.github.io/mint-ui/#/button)、[Ant UI Button](https://mobile.ant.design/kitchen-sink/components/button?lang=zh-CN)
* 通用,包括文字font、颜色color、状态status、皮肤skin
* 布局layout,栅格gird、间距row/col
* 按钮button
* 导航nav
* 标签tab
* 表单form
* 列表list/item
* 进度条/步骤条progress/schedule
* 图标icon
* 模态框modal
* 提醒toast
* 对框dialog
* 弹框actionsheet
* 面板panel

### CSS命名规范
采用BEM命名规范,但是使用'-'进行连接,如`命名空间(bx)-block-element--modifier`<br/>
* block<br/>
是页面中独立存在的区块，可以在不同场合下被重用,如:nav
* element<br/>
是构成Block的元素，只有在对应Block内部才具有意义，是依赖于Block的存在,如nav-item
* modifier<br/>
是描述Block或Element的属性或状态。同一Block或Element可以有多个Modifier,如nav-item-disable
<br/>
需注意一个Block下的Element均属于Block,尽可能的分开命名以防名字过长嵌套过多,Modifier也遵循这个规则。
<br/>
如:bx-card-header与bx-card-header-title应该尽量写出bx-card-header与bx-card-title

<br/>
三种命名规范:

* namespace-block-element-modifier(weui)
* namespace-block-element .is-modifier(mint ui)
* `(*)namespace-block-element .namespace-block-modifier(大多数)`

----------------------------------我是一条分割线----------------------------------

经过再三的纠结和思考,最终决定更改命名规范。
<br />依然采用以上的命名规范,但是对于modifier修改为`namespace-block--modifier`或`namespace-block-element--modifier`
<br />为何做这样的更改决定?
<br />再重新看BEM规范的时候,又有了不一样的体会。虽然接受不了 block__element--modifier 这样的命名规则,但是BEM通过特殊的分割线来区分block、element、modifier,能够让开发人员一眼看出该命名的作用。
<br />于是决定,使用`namespace-block`、`namespace-block--modifier`、`namespace-block-element`、`namespace-block-element--modifier`这样的命名规则
<br />去掉BEM中的双下划线,因为感觉太影响美感太鸡肋了!!!!!但是保留--连接符,可以方便的区分modifier这种可选属性,又不影响美感!!!!

### CSS行为规范
* 书写顺序(自外向内)
  1. Positon 位置信息
  position、top、right、bottom、left、z-index、display、float、overflow等
  2. Box Model 盒模型信息
  width、height、margin、padding、outline、border等
  3. Typographic 文本相关
  font、text-align、line-height、letter-spacing等
  4. Visual 视觉效果
  color、background、transform、transition等

* 巧用注释
  1. 文档注释
  ```css
  /**
   * 顶部注释
   */
   /* 内容注释 */
   ```
  2. 修饰选择器
  ```css
  /*ol*/.breadcrumb{}
  /*p*/.intro{}
  /*ul*/.image-thumbs{}
  ```
* 使用'-'连接符
* 避免使用ID选择器
* 尽量减少选择器的嵌套
* 尽量避免依赖html标签
* 千万不要把 CSS 样式用作 JavaScript 钩子
  ```html
  <div class="btn-default  js-btn-default"></div>
  ```
* 省略 0 时的单位,包括0px、0em、0rem、0%
* 十六进制值全部大写,因为Sketch色值均为大写,尽量使用简写形式的十六进制值
* 省略小于 1 的小数前面的 0

### 注意事项
* CSS选择器是从右向左匹配的(跟DOM的树形结构相关,从叶子节点开始向上匹配)<br/>
  ```css
  .test h3 span { ... }
  ```
  读取顺序:<br />
  1. 先找页面上所有的span
  2. 沿着span的父元素找所有的h3
  3. 最后沿着h3的父元素找所有的.test
* OOCSS
  建立更细粒度的CSS类,提高他的灵活性和可重用性,遵循两大原则
  1. （分离结构和主题）减少对 HTML 结构的依赖
  2. （分离容器和内容）增加样式的复用性

### 需留意与解决的问题
1. 如何防止重名与破坏命名规则?
2. 如何防止页面层级混乱?
3. 如果样式不满足真实使用场景,该以什么方式自定义扩展?
4. 对于使用类似flexible.js时,样式该如何兼容?
5. 如何方便的于未来的组件库整合在一起?
6. 遇到与其他库同时使用时,如何处理样式上的冲突,如z-index的冲突

### 参考
* [WEUI](https://github.com/Tencent/weui)
* [NEC](http://nec.netease.com/standard/css-sort.html)
* [BEM](http://getbem.com/)
* [OOCSS](https://github.com/stubbornella/oocss/wiki)
* [SMACSS](https://smacss.com/)
* [如何看待BEM](https://www.zhihu.com/question/21935157)
* [决战BEM, 10个常见问题及其解决方案](https://zhuanlan.zhihu.com/p/26407119?group_id=837593211068362752)
* [为什么排版引擎解析 CSS 选择器时一定要从右往左解析？](https://www.zhihu.com/question/20185756)
* [前端开发规范手册](http://zhibimo.com/read/Ashu/front-end-style-guide/index.html)
