[译]CSS命名神马的真心难

译自:Naming CSS Stuff Is Really Hard

找到的这篇文章算是对我之前写的 《标签?ID?还是CLASS?》 的再深入。我当时写那篇文章的时候,就有朋友提出了“非语义化”的 class 命名的问题,我当时确实觉得很纠结,简单的想法是“框架性质的表象 class 我没异议……框架的实质是通过降低灵活性达成更广泛的共识,我们个人不要再创造这样的样式就好了”,但没有想到特别好的“套路”,更多的是在实际情况中再分辨。看过这篇文章,我似乎找到了更好的答案。同时顺着文中提到的 Nicolas 那篇文章看下去,也对 OOCSS、BEM 之类的提法有了更多的认同感。特译给大家参考。



这并不是一篇有关 CSS 架构的文章,也并不是一篇有关命名规范的文章,而关乎我们如何定位元素,关乎命名本身,关乎我们如何把元素及其相关的一段样式连接起来。

10 个开发者里有 9 个都同意:在撰写 CSS 中命名什么的部分是最难的了。因为我们无法预知未来。一个 class 名可以在今天完美的应景,但是明天设计发生改变了,可能就不适用了。所以我们需要提炼应景的标记和样式。嗷~

如何面对这一状况呢?那便是让命名尽量显得不太会改的样子。

我们通常会根据三类情况给定一个 class 名:

  • 功能性 class 名
  • 内容性 class 名
  • 展示性 class 名

这几类 class 名是趋向于稳定特质的。如果我们遵循这些命名原则,就会显得更明智,而且我们的 CSS 会更好的适应未来的改变。

功能性 class 名

<button class="positive-button">Send Message</button>

功能性 class 名例如 positive-buttonimportant-textselected-tab。这些元素的样式是基于其功能或含义的。所以其 class 名、样式及这样引用样式的理由,都是强连接的。因此 class 名和样式是相关的。

因为有这些强连接,所以样式是几乎不会被改变的。如果你真的要改变一个 positive-button 的样子,那这个改变也是每个肯定语气的按钮都要改变的。如果你的设计师的想法是改变“肯定语气的按钮”,而不是设置菜单里“增加用户”的按钮,那么这件事就很轻松且易于维护。你考虑的不是哪个独立的页面,而是整个系统。

功能性的 class 名很棒。只要有这个可能,这应该就是你想要撰写样式的方式。但是功能性的 class 名不是所有情况都适用的。

设计并不一定都有逻辑性。当我们讨论按钮的时候,给出一个功能性的 class 名是很容易的。大部分情况下其功能和样式也紧密相关。但是我们撰写的其它 99% 的样式都不太容易给出这样的例子。有的时候这个块区域需要一个内阴影,因为这样看起来很漂亮;有的时候图标需要在 hover 的时候长大一点因为这样很 cute;有的时候文本需要是橙色的,好吧,因为它就是橙色的。一个网站不是每个视觉的部分背后都有功能性的理由,这无可厚非。

所以开发者该怎么应对呢?我们站在了这个十字路口。如果我们不能想出一个合适的功能性 class 名,那么我们不妨基于内容、或者展现给它起个名字。它们也各自暗示着不同的可维护性。

内容性 class 名

<button class="submit-button">Send Message</button>

基于内容的 class 名是描述它们包含的内容的 class 名。如果你曾经见到过类似 submit-buttonintro-textprofile-photo 的 class 名,那些名字就是基于内容起的。

这些 class 名感觉很干净。它们让你的内容 (HTML) 和样式 (CSS) 之间保持简洁的分离。理论上,这可以让你完全改版网站的样式和感官而无需触碰到 HTML。CSS Zen Garden 就是这样的。

现在我们回到最初的问题:“这样做的好处是什么?”

我从来没有被要求改版一个网站而不触碰 HTML。变化是存在各种可能的。当然一些 HTML 可以作为后台系统的集成成果固定下来,但是随着你对 HTML 的失控,这时你还是需要写一些非理想化的 hacky CSS 来应付设计的变化。想想看,CSS Zen Garden 更多的是一个 CSS 技术演示而不是一个可维护的 CSS 的例子。没有必要一味追求在改版的时候只改 CSS。

当你开发一个小网站的时候,内容性的 class 名非常好用。而随着你的网站不断成长,它就感觉越来越不合适了。它们并不易于样式重用。如果你的 login-buttonsubmit-button 看起来一样该怎么处理呢?在你的 CSS 架构里该如何展示这些东西?为保持展现样式块,你不得不写一堆用逗号分隔开的选择器,或者通过预处理器展开。这些组织方式对于大型的项目来说都比较困难。

除非有更好的方式重用样式块……

展示性 class 名

<button class="green-button">Send Message</button>

展示性 class 名用诸如 green-buttonbig-textsquiggle-border 的方式描述一个元素。其名字本身就是对样式的描述。

这些 class 是有助于代码复用的。它们不关心是否用在产品标题上还是名户名或页头。它们只知道这会让文字变大加粗。同时这样的方式还有一个好处是可以优雅的扩展。如你开发一个新组件的时候,你可以把现成的样式贴在你的新标签上。你无须担心在已有的架构中产生并适配新的样式,因为你使用的都是已有的样式。

展示性 class 名也非常易于自我描述。一个开发者在审查代码的时候,round-image 会比 profile-photo 更多的推断出这个元素的样子。

会有争议认为展示性 class 增加了维护成本。因为它模糊了标记和展现之间的界限,很多设计的改变都将会导致 HTML 的改变。如果你预见到了这方面的问题,那么请谨慎的使用。

……但这不是语义化的!

展示性 class 的名声并不好。尽管很多人回避它们因为它们“不是语义化的”,但这里是存在误区的,也被 Nicolas Gallagher 质疑。重要的是区分“语义化的 HTML”和“语义化的 class”。Nicolas 说的非常好:

撰写“语义化的 HTML”的原则是现代化、专业化的前端开发的基础。大部分的语义化都关乎现有的或预期的内容的本质…… ……不过并不是所有的语义化都需要源自内容的。Class 名可以是“非语义化的”。不管使用什么名字,它们都有意义,都有目的。Class 名的语义化是不同于那些 HTML 元素的。

如我写的这些,“非语义化”这个词下面是有红色波浪线的。非语义化的 class 名并不是问题。每个 class 名都有背后的意义。在你写 class 名时,不必刻意追求它是最“语义上适合的” class 名,而要创建为开发者和未来的你提供尽量多信息的 class 名。

总结

功能性 class 名通常是你的最佳选择。当你能够使用它们的时候就尽量使用。如果你无法提取出完全功能性的名字,可以考虑你的项目的本质及其发展。原则上,内容性 class 名更适合小型站点;而展示性 class 名更适合大型站点。

开发者会很在意这种用法。没有人希望一个项目变得难以维护,但是每个人都有不同的 想法通过 class 名来应对这些特殊情况。这时不妨思考一下我们使用的不同类型 class 名的本质,问问自己这样做是否更好的帮助你的项目达成目标。

7 条早期评论

  • 姓名
    梁小米
    评论日期
    2014/09/28 01:08:58
    亲爱的,body的font-size能不能改成100%?电脑上字好大,不美观呢~(位于style.css的25行)

    我可是为了阅读方便,手动在浏览器上改掉了。?(然后打开一个新文章,又废了)
  • 姓名
    囧克斯
    评论日期
    2014/10/15 05:48:11
    @梁小米
    谢谢您的建议,之前也有同学提出来字太大,我从调小了一点,不知现在看着怎么样。谢谢了:)
  • 姓名
    译自:Naming CSS Stuff Is Really Hard | SimBoo的博客
    评论日期
    2014/11/15 01:16:45
    [...]摘自:http://jiongks.name/blog/naming-css-stuff-is-really-hard/[...]
  • 姓名
    云库网
    评论日期
    2015/11/02 02:17:43
    字体有点大,css命名还是标准加习惯为好
  • 姓名
    Sung
    评论日期
    2016/05/03 03:52:45
    写得很好 不过字体太大了 希望能够更改下。
  • 姓名
    迷雾卡夫卡
    评论日期
    2016/05/13 01:29:16
    其实,我觉得展示性的class一样可以略去。我们可以把这些通用样式,抽出来放入common.css中,然后通过继承的方式传给两个完全一样的button。这样展示性的class依然存在,只不过它们只存在于common.scss(也许是common.less),不会污染到html!
  • 姓名
    fuchao
    评论日期
    2017/05/04 03:24:10
    cmd+shift+-

    命名的问题对 team来讲更加重要了,我们在同一项目中遵循统一标准,比如 bootstrap 的时候,更多用正则语法,也就是“非语义”的展示命名,在 vue/angular 项目中更多使用功能性配合 scope 控制范围,放置重复,同时倒是引入了一部分重复和浪费。