CSS 命名规范总结

BEM 命名给 CSS 以及 html 提供清晰结构,命名空间提供更多信息,模块化提高代码的重用,以达到 CSS 命名语义化、可重用性高、后期维护容易、加载渲染快的要求。

首先,这是一篇仅对 CSS 命名的总结,更多 CSS 规范请参考规范文档。其次 CSS 命名并无对错之分,只是不同的命名方式和代码的优雅程度与后期维护有着密切关系。

@iamdevloper pic.twitter.com/4SRgVDDaiC

— Saeed Prez (@SaeedPrez) 2016年7月14日

CSS 很容易写,但是维护它却很难,因为 CSS 声明属性的性质不具备编程语言流程控制的特点,CSS(Cascading Style Sheets)也可以层叠生效,不同地方的 classes 相互影响。CSS 命名是规范中最重要的部分,它几乎就是 CSS 规范的全部,我们也就是依赖它完成对 CSS 的控制。

分离

曾经我们这样定义选择器:

  1. .fl
  2. float: left
  3. .fr
  4. float: right
  5. .mr10
  6. margin-right: 10px
  7. .pb10
  8. padding-bottom: 10px
  9. .hidden
  10. overflow: hidden
  11. .highlight
  12. color: $green

在 html 中添加选择器:

  1. .fl.pb10.highlight

这就是规则分离的做法,将一些确定值的 CSS 规则单独定义选择器,这样做的目的是提高代码的重用,但是也有很多缺点:

  • 可供分离的属性有限,还有很多不确定值的属性,比如 width、color,而且现实布局的多样性使 mr10 这样的分离也很少用到,因此无法做到彻底分离;
  • 分离之后导致 html 中 class 特别多,而且不具有语义化;

既然还是需要添加语义化的 class 来定义一部分样式,那么分离一部分出去也没有意义,操作上缺点远远大于优点。吸取这种命名的优点,现在依然会使用它,但是只保留了少数语义化且常用的,例如:.hidden.highlight

不好的写法

html:

  1. .container
  2. .actions
  3. .card_wrapper
  4. .card
  5. .title.light
  6. .content
  7. .list
  8. i.fa.fa-cog

CSS:

  1. body.events,
  2. body.aaa,
  3. body.bbb
  4. .actions
  5. .card_wrapper
  6. .card
  7. .title
  8. .content
  9. .list
  10. .fa
  11. .another

以上是我们现在常见的写法,但是是需要绝对避免的,虽然 class 有一定语义了,但是并不能真正的重用。class 命名太通用了,我们不知道还有什么地方用到 .title .content 这样的命名,就不敢直接使用,一方面层层嵌套防止冲突,一方面想要重用时就在顶层添加 body.aaa 这样的东西,导致很多样式用不到,写的乱七八糟。

这样一直写下去,旧的 CSS 我们永远不会删,只敷衍写出效果,如此往复循环,最终就会像上面的窗帘,让人忍无可忍。每个页面都有 .content 甚至每个模块都有 .content.content 就毫无意义(.content 不是抽象化的全局共用模块)。深层次的嵌套也会降低渲染效率。

另一种常见的:

html:

  1. .main-news-box
  2. h2.news-title
  3. ul.main-news-list
  4. li
  5. a
  6. span
  7. span

CSS:

  1. .main-news-box
  2. .main-news-box .news-title
  3. .main-news-list
  4. .main-news-list li
  5. .main-news-list a
  6. .main-news-list span

这种写法的问题:

  • .news-title 在别的地方有没有定义?能不能单独使用?其他地方定义的 .news-title 会相互影响,父级更深层次的 lia 也会覆盖现有的定义。
  • 这种命名也有性能问题,CSS 从右向左渲染,例如 .main-news-list a,先渲染页面所有的 a,再渲染 .main-news-list。

BEM 命名

BEM 是一种真正消除不确定性的命名方式,它使得结构样式更加清晰,我们有足够的信心做任何修改。

  • block:模块,名字单词间用 - 连接
  • element:元素,模块的子元素,以 __ 与 block 连接
  • modifier:修饰,模块的变体,定义特殊模块,以 -- 与 block 连接

例如:

  1. .user-home-nav
  2. .user-home-nav-item.user-home-nav-item--small
  3. .user-home-nav-item__icon
  4. .user-home-nav-item__text

CSS 中这样写:

  1. .user-home-nav
  2. &-item
  3. &--small
  4. &__icon
  5. &__text

这样命名的好处:

  • 语义化,此处的语义化不是指 html 标签的语义化,对 SEO 可能也没有任何意义,但是这是一种人阅读的语义化。语义化的重要意义:宁可增加 html 大小,力图使维护变得轻松。
  • 减少层层嵌套,有利于渲染效率。以上 sass 解析之后就是:
  1. .user-home-nav
  2. .user-home-nav-item
  3. .user-home-nav-item__icon
  4. .user-home-nav-item__text
  5. .user-home-nav-item--small

缺点?

  • 有人说又是 __ 又是 --,什么乱七八糟的符号,我并不觉得有任何问题,这种命名让结构十分清晰,只看 html 或 CSS 就能看出它对应的模块或者模块的元素或者不同类型的模块,后期维护的增删也十分确定。
  • 长长的 class 名增加了 html 的字节。从加载速度上来说,当然是名字越短越好。但是这个对应的就是语义化,取舍上我更倾向于语义化。

BEM 的问题

但是 BEM 最大的问题却是这个:如何给 modifier 下的 element 定义规则呢?

  1. .user-home-nav
  2. &-item
  3. &--small
  4. .user-home-nav__icon
  5. .user-home-nav__text
  6. &__icon
  7. &__text

这样做太不优雅了,太违背 sass 的优雅性质了。或许是我没有找到更好的写法?

还能产生更多的写法,例如 .user-home-nav-item--small__icon.user-home-nav-item__icon--small,但是或多或少会存在问题,还是尽量保持简单。

其他问题:

  • 如何确定一个 block?就像上面 .user-home-nav-item 也可以写成 .user-home-nav__item,如果 item 下有 title,那么就是 .user-home-nav__title,以避免写成 .user-home-nav__item__title,但是如果 nav 已有 title .user-home-nav__title 了,或许我们要把 item 下的 title 写成 .user-home-nav__item-title,总之为了使 BEM 也不至于复杂化,命名上也许还是要纠结一番。所以我最终写成了 .user-home-nav-item,也许可以这么写下去,没有 B 和 M,trello 貌似就是这样,例如:.attachment-thumbnail-details-options-item-text
  • BEM 导致 CSS 规则重用性降低,如果重用尽量考虑写成通用模块.

BEM + 命名空间

命名空间定义 block 间的关系,这种方式网站上还没有大范围使用,最常见的如 .js- 表示定义 JavaScript 钩子,不用于定义样式。常见命名空间:

  • o-:表示一个对象(Object),如 .o-layout
  • c-:表示一个组件(Component),指一个具体的、特定实现的 UI。如 .c-avatar
  • u-:表示一个通用工具(Utility),如 .u-hidden
  • t-:表示一个主题(Theme),如 .t-light
  • s-:表示一个上下文或作用域(Scope),如 .s-cms-content
  • is-,has-:表示一种状态或条件样式。如 .is-active
  • _:表示一个 hack,如 ._important
  • js-:表示一个 JavaScript 钩子。如 .js-modal
  • qa-:表示测试钩子。

例如一个圆形头像组件:

  1. .c-avatar-circle
  2. &__img
  3. display: block
  4. vertical-align: top
  5. max-width: 100%
  6. border-radius: 100%
  7. &__name
  8. text-align: center

以上,BEM 产生的重用性问题还是没有解决,如何解决?

模块

模块化类似于分离的概念,也是分离进化的结果,我们从分离中提取出 .hidden {overflow: hidden} 这样的命名,进而扩展 .avatar {} 这样的命名,不再只包含一条规则。看一下 airbnb 的圆形头像写法:

html:

  1. a.pull-right.media-photo-badge.card-profile-picture.card-profile-picture-offset.is-superhost
  2. .media-photo.media-round
  3. img

CSS:

  1. .card-profile-picture
  2. width: 60px
  3. height: 60px
  4. &-offset
  5. position: relative
  6. top: -40px
  7. margin-bottom: -40px
  8. &.is-superhost
  9. position: relative
  10. img
  11. width: 56px
  12. height: 56px
  13. .media-photo
  14. backface-visibility: hidden
  15. position: relative
  16. display: inline-block
  17. vertical-align: bottom
  18. overflow: hidden
  19. background-color: #bbb
  20. .media-round
  21. border-radius: 50%
  22. border: 2px solid #fff

这个是比较复杂,相对特例的。.media-photo.media-round 是典型的抽象出来的模块,一个定义照片的基本属性,一个定义圆形属性。.card-profile-picture 是特定的命名定义特定具体的值。

总结

  • 基本:以英文单词命名,避免无意义的缩写,以 - 连接。
  • 我在一开始使用 BEM 的时候,也有很多疑惑,而且现在也不确定它完备的用法。
  • BEM 不是万能的,但是无论如何 BEM 是应该使用的方法。
  • 命名空间给 CSS 命名提供更多信息。
  • 定义模块提高代码的重用。
  • CSS 命名要求:语义化易于理解,可重用性高,后期维护容易,加载渲染快。

参考文章

CSS 命名规范总结的更多相关文章

  1. CSS命名规范

    DIV+CSS规范命名大全集合 前端人员必看CSS命名规范 整理: 文件名必须由小写字母.数字.中划线组成 ).所有的命名最好都小写,一律采用小写加中划线的方式,不允许使用大写字母或 _2).属性的值 ...

  2. html,css命名规范 (转)

    HTML+CSS命名规范总结 1.HTML部分 1.1添加必须的utf-8的字符集,并且使用HTML5的简洁 方式: <meta charset="utf-8"> 1. ...

  3. web前端开发CSS命名规范参考

    做为一个web前端工程师,每天接触HTML.css就像吃饭一样,但是作为一名合作.优秀的web前端工程师,对DIV+CSS命名还是有一定的规范的,本文整理了一份web前端开发中DIV+CSS各种命名规 ...

  4. CSS 命名规范及标题供参考与学习

    一.CSS 命名规范   XHTML-CSS写作建议 所有的xhtml代码小写 属性的值一定要用双引号("")括起来,且一定要有值 每个标签都要有开始和结束,且要有正确的层次 空元 ...

  5. Html+CSS命名规范:

     Html+CSS命名规范: 1.样式命名: 2.样式文件命名:

  6. css命名规范: BEM 的命名法

    整理自:前端早读课[第1183期]这些 CSS 命名规范,将省下你大把调试时间 试图解决 3 类问题: 仅从名字就能知道一个 CSS 选择器具体做什么 从名字能大致清楚一个选择器可以在哪里使用 从 C ...

  7. CSS命名规范(规则)常用的CSS命名规则

    CSS命名规范(规则)常用的CSS命名规则   CSS命名规范(规则)常用的CSS命名规则   头:header   内容:content/container   尾:footer ...

  8. 通用CSS命名规范

    一.文件命名规范 样式文件命名主要的 master.css布局,版面 layout.css专栏 columns.css文字 font.css打印样式 print.css主题 themes.css [/ ...

  9. CSS 命名规范将省下调试时间

    我听说很多开发者厌恶 CSS.而在我的经验中,这往往是由于他们并没有花时间来学习 CSS. CSS 算不上是最优美的『语言』,但迄今二十多年来,它都是美化 web 举足轻重的工具.从这点来说,也还算不 ...

随机推荐

  1. Heap Spray原理

    Heap Spray定义基本描述 Heap Spray并没有一个官方的正式定义,毕竟这是漏洞攻击技术的一部分.但是我们可以根据它的特点自己来简单总结一下.Heap Spray是在shellcode的前 ...

  2. 清空iframe的内容

    document.getElementById("web").contentWindow.document.body.innerText = "";

  3. Android -- 图像处理(信息量超大)

    Android的图像处理提供的API很帮,但是不适合用来写游戏,写游戏还是用专门的引擎比较好. Android的图像处理还有3D的处理的API,感觉超屌. 我先分享一下Android的一般的处理,比如 ...

  4. 用thinkphp操作session

    写了一段代码,对session进行一些常用的操作: <?php namespace Home\Controller; use Think\Controller; class Demo1Contr ...

  5. angularjs中响应回车事件

    下面这个示例在输入框键入回车键或者点击按钮时,将输入框的值置为"Hello World!":(黄色背景内容为响应回车事件涉及到的代码) <html ng-app=" ...

  6. Shodan:黑客的物联网搜索引擎

    记得看过一个电影.里面的科学家开发了一个超级系统,能够实时监控全部可用摄像头.让逃犯无处遁形. Shodan这个新型的搜索引擎可能会让这个想法变成现实. 和Google这些传统互联网信息搜索引擎不同. ...

  7. js 替换json对象中的键名

      js 替换json对象中的键名 CreateTime--2018年3月30日15:38:50 Author:Marydon 情景描述: 有个json数组,现在需要将json对象中的key替换掉,值 ...

  8. yum groupinstall报错,处理方法

    http://www.cnblogs.com/xiaoluo501395377/archive/2013/05/21/3089970.html ===== 创建repo库 # createrepo - ...

  9. Bootstrap 3 Menu Generator

    Bootstrap 3 Menu Generator

  10. CDH quick start VM 中运行wordcount例子

    需要注意的事情: 1. 对于wordcount1.0 ,按照http://www.cloudera.com/content/cloudera/en/documentation/HadoopTutori ...