CSS 设计模式

大型的 CSS 项目中,往往会遇到 CSS 结构混乱、多人协作命名冲突、没有组件化无法复用…等等问题。为了解决这些问题于是引入 CSS 设计模式,用 BEM 来解决命名空间的问题,用 SMACSS 来解决代码分层问题,用 OOCSS 来解决解构复用问题。

BEM

对于 CSS 选择器的命名空间,一般的做法是通过选择器嵌套来约束命名空间,但是这种方式带来了很多问题 – 嵌套层次深不但影响了性能也导致了重度的 DOM 依赖,还有最重要的是命名冲突。

一个优秀的 CSS 命名方案,应该要解决以下问题:

1
2
3
* 具备 NameSpace;
* 不能与嵌套的业务样式命名冲突;
* 独立、对上层不过度依赖;

BEM 的出现解决了上述问题。

BEM 中,B 代表 Block(Component)、E 代表 Element、M 代表 Modify。规定用 __ 连接 E,用 --连接 M,用 - 连接单词和命名前缀。比如:

1
2
3
4
.m-page
.m-page__item
.m-page__item--cur
.m-page--center

注:BEM 最多只有三层,不可能存在嵌套的 Element,比如 .m-page__item__anchor--cur

SMACSS

SMACSS 是一个比较全面的 CSS 规范,它不但规范了命名空间,还对 CSS 进行了分层。具体到项目中,只参考它的分层。

命名前缀

命名前缀用于说明 UI 类型归属,可以结合 BEM 一同使用,用于说明 Block 的类型。

  • g-栅格

简单栅格系统:用户后台 g-hdg-fdg-bdg-sdg-mn,前台和中间页 g-headg-bodyg-foot

  • f-原子类

常用原子类:f-bfcf-clearfixf-ellipsisf-showf-hidef-cb…。

定义原子类必须谨慎,功能性的原子类还好(f-clearfixf-bfc),描述性的原子类必须谨慎(比如 f-w100)。原子类的使用场景是供后端使用的,或者前端 fix issue 时紧急使用。

原子类的缺陷:与 inline style 无异,没有做到结构与样式的分离;容易导致 class 臃肿。

  • u-元件

常用元件:u-btnu-iptu-selectu-lineu-link…。

利用 OOCSS 来对页面元素进行抽象,是一种非常好的做法,这样可以通过继承,组合出不同的样式。但是也有导致 class 的臃肿的缺点,不过为了前者的实用性,后者的这点缺点也算不了什么。

  • m-组件

常用的 UI 组件:m-tabm-tablem-formm-pagem-dialogm-btnsm-selectm-search-box...m-headerm-footer…。

UI 的组件化也就是 HTML、CSS 的组件化。模块化、组件化的目的是封装(作用域隔离)、复用,这使得代码简洁易读易维护,按照最小组件化原则,非常有利于项目在快速迭代中的发展。

组件化原则:

1
2
3
* 组件化抽象的第一原则是复用(这也是 m 与 c 最主要的区别);
* 各个组件独立划分,充分解耦,遵守职责单一原则;
* 业务 m 不能与全局 m 冲突,业务 m 要带上业务前缀(比如,m-header-mall),必要时还要加上模块前缀(比如,m-title-mall-index);

自定义组件:

当组件化不满足场景时,可对 modify 进行自定义(组件不满足场景大部分是 modify 不满足):

1
2
3
4
m-page--center
c-choiceness-stage__carousel--junior
c-choiceness-stage__carousel--high
c-choiceness-stage__carousel--senior
  • c-模块

整个 UI 都可以被模块化,包括业务,使用 c-xx 来作为命名前缀(c 指代 component,表示模块,而非 custom)。

component 和 module 的区别:component 包含 module,module 是 component 的组成部分,组件一般是可高度复用,可在整个项目或者跨项目通用的,这里的 c 其实指的是不可复用的业务模块(模块 - 组件 = 不可复用的业务模块),主要目的是封装,不具备 m 一样的复用能力。

1
c-login      # login 不能被复用,所以这里不能用 m-login

OOCSS

OOCSS 只是一种思想,并没有具体的规范,用 OO 的方式来对 CSS 进行解构抽象,能够达到很好的作用域封装和复用效果。

1
2
3
.u-btn .u-btn--normal .u-btn--gray
.m-page .m-page--center
.m-tips .m-tips--success