许多开发者非常讨厌 CSS,这导致了他们不愿意花太多时间去学习 CSS。
虽然 CSS 不是一门好的“语言”,但 CSS 成功的为 Web 提供了20年的样式支持,理论上不会太差。
当你在项目中写了大量的 CSS 后,你会发现 CSS 的致命缺陷 -- 维护成本巨大。
加上糟糕的 CSS 命名,会让你体会到被它支配的恐惧。
下面我将介绍几种 CSS 命名规则,解救你于水火之中。
用连字符命名
在 JavaScript 中,我们喜欢用驼峰命名法。
var redBox = document.getElementById('...')
但它并不适合 CSS。
建议不要这样写:
.redBox {
border: 1px solid red;
}
最佳写法:
.red-box {
border: 1px solid red;
}
这是非常标准的 CSS 命名写法,可读性更好。
同样的,CSS 属性也要用连字符:
// Correct
.some-class {
font-weight: 10em
}
// Wrong
.some-class {
fontWeight: 10em
}
BEM 命名规则
不同的团队可能有不同的命名规则,有的团队喜欢用连字符来命名,有的团队喜欢用更结构化的命名规则 -- BEM 命名规则。
通常 CSS 命名需要解决三个问题:
- 通过名字就要知道它是干什么的。
- 通过名字就要知道它在哪里被使用。
- 各个名字之间的关系。
你有没有见过这样的命名:
.nav--secondary {
...
}
.nav__header {
...
}
这就是 BEM 命名规则。
如何向5岁小孩解释 BEM
BEM 试图将整个用户界面划分成各个可重用的小组件。
想象下下面这幅图:

这个火柴人(stick-man)表示一个组件,类似于块设计(block of design)。
你可能已经猜到,BEM 中的 B 指的就是 block。
在用户界面中,‘block’ 指的就是 navigation,header,footer 等等。
所以对于这个组件,我们可以命名为 stick-man。
.stick-man {
}
我们使用连字符的命名。

E 表示元素(Element)
BEM 中的 E 表示元素。
整个块设计中的元素很少有孤立存在的。
比如火柴人,拥有头(head),手(arms),脚(feet)。
我们可以把 head,arms,feet 看成火柴人的子组件。
使用 BEM 命名规则,元素命名需要两个下划线:
.stick-man__head {
}
.stick-man__arms {
}
.stick-man__feet {
}
M 表示可变部分(Modifiers)
BEM 中的 M 表示可变部分。
如果把火柴人修改成红色或者蓝色:

在真实的界面的中,比如红色的按钮或者蓝色的按钮,其中红色和蓝色是可变部分。
使用 BEM 命名规则,可变部分命名需要两个连接符:
.stick-man--blue {
}
.stick-man--red {
}
我们再看下面这个例子,有个不同大小头部的火柴人:

.stick-man__head--small {
}
.stick-man__head--big {
}
注意,双连字符。
这是 BEM 基础用法,进一步了解。
为什么要使用命名规则
在计算机科学中只有两个麻烦事:缓存失效和命名 — Phil Karlton
命名很麻烦。所以我们要尝试让它变得简单,减少以后维护代码的成本。
如果你用 BEM 命名规则,可以让你通过名字就能轻易的分辨出你设计的组件。
用于 JavaScript 的 CSS 命名
我们先来看一段我项目中的 HTML 代码:
<div class="siteNavigation">
</div>
通过上面的学习,我们来重构下这段 HTML:
<div class="site-navigation">
</div>
gg,报错了。
因为在 JavaScript 代码中有段这样的代码:
//the Javasript code
const nav = document.querySelector('.siteNavigation')
因为我们改变了 CSS 名称导致了 JavaScript 代码报错。
为了避免上述问题的发生,不同用途的 CSS,我们要采用不用的策略。
1.使用 js- 命名
用一个 js-* 命名来表示与 DOM 有关联的名称。
比如:
<div class="site-navigation js-site-navigation">
</div>
JavaScript 中的代码:
//the Javasript code
const nav = document.querySelector('.js-site-navigation')
任何看到 js-site-navigation 类名就会想到,这个名称会用于 JavaScript 代码中。
2.使用 Rel 属性
还是上面那个例子,我们也可以这样写:
<div class="site-navigation" rel="js-site-navigation">
</div>
JavaScript 代码:
const nav = document.querySelector("[rel='js-site-navigation']")
Web 开发最神奇的地方就是,同一个问题,你可以用多种方式去解决。
3.不要用来储存数据
很多开发者喜欢在 DOM 上储存自定义数据,最好别这样用。如果必须要这样,请参考 Twitter 的用法:

写 CSS 注释
这个部分和命名规范没什么关系,好的注释也会方便你维护代码。
很多开发者不愿意写 CSS 注释,或者写的很少,我个人觉得注释是很有必要的。
应为 CSS 并不是一门有没的“语言”,所以好的注释会帮助你理解代码。
怎么写 CSS 注释呢?强烈推荐 Bootstrap 的源码。
最后
为大家推荐一本 CSS 进阶的书。

感谢阅读!
本文翻译自 medium 上 Ohans Emmanuel 的 CSS Naming Conventions that Will Save You Hours of Debugging