Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

模块化的 CSS 命名规则

  以下文章可能是一个旧版本,更新维护中的版本请移步 Github 查看:
  https://github.com/YanagiEiichi/modularly-naming-for-css

  由于我自己的 CSS 命名方式一直都没一套标准,最近公司也需要一套这样的标准,所以在此整理出一套可以用的来分享给大家。不过这套东西在我这里并没有对一些太细的地方做约定,目的只是为了模块化,为了减少冲突。也许还需要配合其他 CSS 风格规范才能完整。

模块的概念

  虽然大家都在说「模块」,但实际上大家对「模块」的定义根本就不一样,很多讨论没法得出结理论的原因就在于此。就像同样的 PM2.5,香港都红色预警了大陆依然标着「优」。概念不同的话说什么都是耍流氓,所以我们既然要说「模块化」,那么我们首先就要给「模块」一个明确的定义。
  我所说的「模块」指的是全局定义的名称,无论它是一个组件,还是一个全局通用规则,甚至是一个页面的业务类,比如: .clearfix {}
.dropdown {}
.homepage {}
  这些对我而言都是「模块」。模块的名称只允许字母和数字,不允许其他符号。在这套「模块化的 CSS 命名规则」中,我们还将模块分为下面几类以便于管理,并且这些不同的分类有不同的命名规则:
  • 页面,与 HTML 文件对应的页面部分,比如 .homepage
  • 组件,带固定 HTML 结构的通用部分,比如 .dropdown
  • 修饰,没有 HTML 部分的通用样式,比如 .clearfix
  对页面类的模块命名通常是根据页面路径来做的,页面路径这东西本身是无规范的,但我建议使用 RESTful 的命名规范,对页面路径使用名词。所以我们应该尽可能地对这类模块使用名词来命名。
  组件类的模块命名通常会根据组件的功能来决定,虽然经常会是动词,但我们也应该将其变换成同词根的名词形式来给组件命名。所以我们同样是尽可能地对这类模块使用名词。
  最后是修饰类,它们没有 HTML 结构,甚至有些都没有自身样式(只有在多类选择时才设置样式)。所以对于这类模块我们会使用尽可能地使用形容词(偶尔也会出现一些副词)。
  除了这些词性上的命名规则外,这套「模块化的 CSS 命名规则」中所有「-」用于表示层级关系,禁止用于单词分割。分词方式可以根据自己的喜好或视团队情况来做进一步约定,这里不做限制。比如可以直接抽掉空格让单词堆在一起,也可以使用驼峰命名来分割单词。

模块的子规则

  光有模块当然不行,模块内部还有一系列复杂的子样式,通过「-」前缀的方式来命名。比如 .homepage {}
.homepage-banner {}
.homepage-news {}
.homepage-news-more {}
  这里的.homepage-banner.homepage-news以及.homepage-news-more都是.homepage这个模块下的子规则。对于某个模块下的子规则总是以所在模块名作为前缀,以「-」分割。至于后面有多少个层级就视业务而定,此处不做要求。所有子规则扁平地定义,不要使用后代选择器,比如下面这个写法是不推荐的: .homepage .homepage-banner {}
.homepage .homepage-news {}
.homepage .homepage-news-more {}
  这么做会徒增 CSS 选择器的优先级,使以后的样式层叠受到阻碍。
  也许有人会问,为什么搞这么麻烦?直接在模块上使用后代选择器不是很安全吗?比如: .homepage .banner {}
.homepage .news {}
.homepage .news-more {}
  其实这是非常糟糕的解决方案。首先,这个做法同样有上面的选择器优先级问题。即使不考虑优先级问题,这个做法还有更坏的影响。虽然我们在组件后代的选择器中写规则不会影响到其他组件,但这种做法无法确保其他全局模块不会和当前组件的子规则命名冲突。比如我像上面这样直接使用.homepage .news来选择.homepage下的.news部分,虽然在这里的.news中设置样式绝对是安全的,但如果将来的业务需求来一个名为news的页面,我们就无法再使用.news作为那个页面的组件名,因为会和这里的.news冲突。所以如果这么做,以后添加任何一个模块都要胆战心惊,总是害怕和其他模块的子规则冲突。我的博客目前就是这种糟糕的方案,所以虽然代码都是自己写的,但那些两年前写的代码现在维护起来都已经很困难了。
  上面规定子规则必须是以所在模块的模块名为前缀就是为了避免这种冲突。

模块的嵌套

  模块允许出现在任何地方,允许任意嵌套,且允许一个元素上设置多个模块。比如 <style>
.yellow { color: yellow; }
.green { color: green; }
.yellow.green { color: yellowgreen; }
</style>
<div class="yellow">yellow
   <div class="green">green</div>
</div>
<div class="yellow green">yellowgreen</div>
  也可以在一个模块中使用后代选择器去选择其包含的另一个模块,比如: <style>
.homepage .clearfix { border:1px solid red; }
.homepage-floating { float:left; }
.clearfix { overflow: hidden; }
</style>
<div class="homepage">
  <div class="clearfix">
    <div class="homepage-floating">floating</div>
  </div>
</div>
  如果是模块自嵌套,也许还要考虑自冲突的问题。关于这个点我不想展开说,因为内容实在太多,反正模块自嵌套的行为是不推荐的。

开发

  为每个模块编写文档,统一管理。因为一个项目中会定义很多模块,而且模块的使用方式有时很很特殊(因为支持多类选择),所以文档是必须的。至于写在哪儿这里也不做约定。可以写在文件注释中,也可以单独整理文档。

关于「模块化的 CSS 命名规则」

  其实这套「模块化的 CSS 命名规则」目前也仅仅是一套「可以用」的东西,里面还有很多我没想到的点。我想慢慢完善它,可能会去开个 github 仓库吧。至于这篇文章是否会持续更新那就难说了(其实维护一篇文章的更新不太现实),可以把这篇文章视为一个首发版,具体的定义和变更应该是会丢在 github 里的(目前还没建仓库,过段时间会就把仓库链接接丢在这儿)

网名:
54.144.24.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^