阅读 8665

如何管理 CSS “内裤”

修正于 2018-10-21。为了文章生动,之前用了太多过于夸张的修饰手法,以至于让很多朋友忽略了内容本身。基于网友的评论和指出的不足。略微修改了文风,删除了多余的废话,梳理了文章大纲。

命名 是我认为 CSS 里最难的问题没有之一。

CSS 是一个不强调逻辑,而更侧重表现的一门所见即所得的语言。你写了一个属性它就有一个样式,就好比嗑瓜子,你每嗑一下都能及时的得到一个奖励。这种愉悦感是别的开发语言所不具备的。

CSS 也不像其它侧重逻辑的语言,有比较多的代码管理方式。你能管理 CSS 的工具只有两个,一个是文件引用,另一个是命名。通常为了减少页面 HTTP 的请求,我们会尽可能的将 CSS 文件合并。于是靠文件引用这个方式来管理 CSS 的这条路也就显得特别的窄了。

我们都知道 CSS 的作用域是全局的,只要你引用了一个 CSS 文件,它就会影响你整个页面。于是,CSS 代码管理的重任就全压在了命名这一条路上。

所以简单的说,你能搞定 CSS 的命名,就能管理好 CSS。

管理 CSS 就好比管理“内裤”

对于 CSS 的管理,我这边举个不恰当但是很贴切的类比,就是类似于日常生活中内裤的管理,是的就是日常穿的内裤,和 CSS 中的“类库”谐音(我太有才了)。

前面有讲到,对于 CSS 的管理我们基本只能通过命名的方式去管理。这听起来似乎是一件值得开心的事,因为只有一条路,所以大家都没得选。然而出乎我们意料的是,即使只有一条路,大家也是走得五花八门。

举个例子,比如我们有 7 条不一样的内裤,如果只用命名的方式去管理内裤,会出现多少种可能?

按日期 按颜色 按材质 按花纹 ...
.星期一{} .红色{} .纯棉{} .格子{} ...
.星期二{} .黄色{} .涤纶{} .横条纹{} ...
.星期三{} .蓝色{} .氨纶{} .波点{} ...
... ... ... ... ...

就像一千个读者就有一千个哈姆雷特一样,不同的人对于同一件事物的命名方式是不一样的。因为对于自己喜欢和熟悉的东西,对于其它的人来说都基本上是不熟悉的。不信你可以问问你的同事,你们归纳和命名内裤的方式很大概率是不一样的。所以这个的可能性是无限的。

当然如果只有 7 条内裤,你和我的命名方式不一样就不一样呗,我只要能看懂基本也就还好。可是,当我们对于内裤的管理上升到了的概念的时候,一切就没有那么容易了。

假设你爸是挖矿的,你家很有钱。而你又特别喜欢买内裤,赤,橙,黄,绿,青,蓝,紫,彩色的,蕾丝的,莫代尔的,纯棉的,紧身的... 各式各样的内裤共计 100 ,请问你要怎么命名这 100 条内裤?

此时你会发现上面管理 7 条内裤的方式,任意一个方式都显得力不从心。所以要怎么办呢?

管理 CSS “内裤” 的通用方法

之前有讲到,管理 CSS 的问题就是 CSS 命名的问题。所以我们看看目前现有的最流行的解决 CSS 命名的通用解决方案 BEM。

因为我不是 BEM 的拥护者,之前举的例子被网友评论打脸了,这边就直接讲结果吧。

.block__element--modifier{ /* */ }
复制代码

很直观的可以看到引用了 BEM 之后,我们的 CSS 就有了,三级的作用域。这个怎么解释呢?

很简单,之前我们命名 7 条内裤的方式是一维的。但是用 BEM 之后,可以看作是一个长宽高各 10 的三维立方体。你要找一个东西,你只需要知道对应的长宽高对应的坐标就能找到。类似:

.长1__宽2--高3{ /* */}
复制代码

是不是一下子就简单了很多。BEM 系统的解决了 CSS 的命名问题,并且它的维护性和拓展性也是非常棒。所以它是非常值得推荐的管理 CSS 代码的解决方案。感兴趣的同学可以下来自己了解一下。

这里呢,我是想说是我不喜欢 BEM 的点(感觉又要打脸了)。与其说不喜欢 BEM,倒不如说我连 CSS 命名本身都不喜欢。为什么这么说呢?因为对我来说命名真是一件非常痛苦的事情。

在我写代码的时候经常会遇到这样的问题,有两个非常像的模块,但是它们又有些许的不同,为了公用他们相同的样式,你又必须将这部分抽象出来,可是抽象出来的这个部分,又不能倾向于这两者其中一个,你要怎么命名呢?就好比:

/* 这个例子不是 BEM 的正确使用姿势,这里只是作为参考 */

.柜1__屉2--内裤,.柜2__屉2--内裤{
    名称:贴身的下身内衣;
    大小:中号;
    颜色:粉色;
}
.柜1__屉2--内裤{ 
    适合性别:男; 
}
.柜2__屉2--内裤{ 
    适合性别:女; 
    款式:蕾丝;
}

<div style="柜1__屉2--内裤">一条内裤</div>
<div style="柜2__屉2--内裤">另一条内裤</div>
复制代码

你想为上面这两条内裤公共的部分抽象一个通用的类,请问要怎么命名?然后更可怕的是,此时又来了第三条内裤:

.柜2__屉3--内裤{ 
    名称:贴身的下身内衣;
    大小:中号;
    颜色:红色;
    适合性别:女; 
    款式:蕾丝;
}
<div style="柜2__屉3--内裤">又一条内裤</div>
复制代码

然后你又发现,之前好不容易命名好的通用类名,不能用到这第三条内裤上。然而第二条内裤和第三条内裤又有了公用的部分,这部分是不是又可以进一步抽像呢?一旦抽象,就意味着又要取一个名字,然而此时你又该怎么取名呢?这次拓展两步,我的已经崩溃了。

当然在实际开发中,我相信大家有更优秀的命名方式,来解决这个实际的问题。这里只是用这种夸张的方式来证明命名是一件非常不容易的事情(不用较真我的使用姿势是否正确)。

你要的是内裤,不是内裤放在哪里

我们每次找不到自己内裤的时候,会本能问:“妈!我昨天穿的那条内裤在哪儿啊?”

妈妈通常会不耐烦的回答:“昨天不就告诉你了在第一个柜子的第二个抽屉,这样的问题你到底还要问几遍?”

.柜1__屉2--内裤{ 
    名称:贴身的下身内衣;
    大小:中号;
    适合性别:男; 
    颜色:黑色;
}
复制代码

“第一个柜子第二抽屉”,这听起来很像 BEM 命名的 的方式,当然它能非常简单直白的告诉你内裤放在哪里。

可是不知道大家有没有想过这样的问题,如果我们问:“妈!我昨天穿的那条内裤在哪儿啊?” 啪!你妈妈直接就把内裤扔你脸上了,这种方式是不是才是我们更希望看到的结果。是的,要啥内裤坐标啊,直接把内裤给我不就好了。我要的是内裤,不是内裤放在哪里。

CSS 是什么?CSS 是层叠样式表,而 class(类名)显然不是,它只是 CSS 和 HTML 之间的钩子

名称:贴身的下身内衣;
大小:中号;
适合性别:男; 
颜色:黑色;
复制代码

这些东西,才是真正意义上的我们想要的“内裤”的样式。而.柜1__屉2--内裤只是一个告诉你 “内裤” 放在哪儿的坐标。

那在实际开发过程中,怎么样才算是想要内裤的时候,内裤就出现在我们手中呢?

<div style="名称:贴身的下身内衣;大小:中号;颜色:粉色;适合性别:男;">一条内裤</div>

<div style="名称:贴身的下身内衣;大小:中号;颜色:粉色;适合性别:女;款式:蕾丝;">另一条内裤</div>
    
<div style="名称:贴身的下身内衣;大小:中号;颜色:红色;适合性别:女;款式:蕾丝;">又一条内裤</div>
复制代码

是的,通过 style 直接写 CSS 属性,就能简单粗暴的把“内裤放到别人手中”。而这也是我认为最符合 CSS “所见即所得” 的方式。

想要什么样式我就写什么样式,不用花时间去为我的样式创建一个自认为很好看,但是别人看不懂的类名。我也不用考虑命名污染的问题,因为根本连命名都没有。也正因为连命名都没有,所以也不需要纠结上面提到的任何关于命名让人头疼的问题。

只是因为我们大家都太习惯创建 class 了,导致我们在写样式的时候,第一步想不是样式本身而是创建一个 class。在我看来这是有一点本末倒置的。

总结一下就是:当我想要“内裤”的时候,我希望的是“内裤”就直接出现在我的手里,而不是得到一个能精确告诉我“内裤”放在哪里的坐标。不管这个坐标的命名规则听起来是有多么的好。

一旦有了命名,我在管理 100 条“内裤”的同时,还得管理比“内裤”本身量级更复杂的这 100 个类名。

管理内裤的原材料而不是内裤

我们之所以会需要去管理代码,很大一部分原因是因为我们想要去复用它造成的。简单的来说,现买现用,穿完就扔的内裤,是不需要你花时间和精力去管理的。

上一节中我们放弃了复用样式这个想法,利用 inline css,在解决代码管理问题的同时,还得到了一种将重心聚焦在 CSS 样式本身的编程体验。

正是因为我们放弃了命名,所以才解决了代码管理问题,可是想要复用就必定意味着要命名。这听起来似乎是一个悖论。

那有没有一种方式是可以跳出这个怪圈的呢?答案当然是有的,那就是放弃管理“内裤”,而是转向去管理“内裤”的原材料。我们将之前需要管理的 100 条内裤的原材料列举如下:

  • 布类型:棉,麻,涤纶,氨纶,莫代尔...
  • 颜色:赤,橙,黄,绿,青,蓝,紫...
  • ...

基于之前的例子,我们现在的代码会变成什么样的呢?

<style>
  .贴身的下身内衣{ }
  .中号{ }
  .男{ }
  .女{ }
  .黑色{ }
  .红色{ }
  .粉色{ }
  .蕾丝{ }
</style>

<div class="贴身的下身内衣 中号 粉 男">一条内裤</div>
<div class="贴身的下身内衣 中号 粉色 女 蕾丝">另一条内裤</div>
<div class="贴身的下身内衣 中号 红色 女 蕾丝">又一条内裤</div>
<div class="红色">一匹红色的马</div>
复制代码

首先,因为这些原材料都已经是不能拆分的最小单元,所以他们的名字能非常容易的固化下来,形成一个通用的“类库”。每次创建新项目的时候,你只需要略微的修改就可以复用起来。

虽然为了解决样式复用的问题我们还是有创建类名,但因为这些命名是不可以拆分并且容易固化的,所以管理的难度会小很多。并且随着,时间的推移,原材料的膨胀率是非常小的。组件化如果做得好,原材料甚至可以做到只减不增。

更惊奇的是,这些原材料可不只用于内裤上,它还可以应用到衣服,裤子,鞋子...等等一系列的东西上。你甚至可以用这个原材料,把一匹马涂成红色。这就是我们视角改变了之后,整个思维方式的巨大改变。而是将复用发挥到极致。

这种将样式原子化的思维方式,是来自雅虎团队的 Atomic CSS (简称 ACSS )。毫不吹嘘的说,基于这套理论,我是我遇到的前端程序员中 CSS 原型稿写的最快的程序员(可能我认识的人本来就不多)。

在这里有必要解释一下,我全篇所有的论证都是基于“库”的概念的。如果你只是创建一个简单的运营活动页 ACSS 那你只能用到 ACSS 这一个特性,而它更大的优势代码管理这一块是体现不出来的。

因为组件化思维正是当下最流行的时候。而 ACSS 是和组件化思维特别 Match 的一种方式。所以特别希望 ACSS 能被大家看到。当然个人能力有限,如果不恰当的地方可以给我留言,我们一起探讨。

内裤是工业品不是艺术品

到这里可能有的同学会说,你这个原材料拆分的明显没对,布类型不是还有竹炭纤维,甚至太空材料的,颜色还有红蓝渐变或者五彩斑斓的黑。

对于我们大多数男性程序员来说,内裤无非就是棉的和不是棉的两种,颜色无非就是黑,白,灰。即使不是程序员,你也很难会发现,普通的人会买到,赤,橙,黄,绿,青,蓝,紫这么多种颜色的内裤。

举这个例子是想说明什么,内裤是工业品而不是艺术品。工业品注定会控制原材料的种类以降低成本的。而真正会把内裤当艺术品的人,也就不会因为没钱,而不会去考虑复用内裤的问题。

在我们网页的开发也是一样的,如果你的网站不是走艺术类的网站,你却发现你的原材料提供商(设计师),光是从颜色上就给你提供了超过了十几二十几种颜色,那他一定是有问题的。

如果你的设计师,是对自己的设计语言是有极致约束能力的,那对于我们开发者来说这真的是一件非常开心的事情。

相关阅读

  1. quickLayout.css-快速构建结构兼容的web页面 @张鑫旭
    男神作品,强推;
  2. 「英」在组件化浪潮中重新思考CSS @johnpolacek
    虽然是英文,但是网页做得像PPT一样,通俗易懂,强推;
  3. 「CSS思维」组件化VS原子化 @ziven27
    我的一篇专门解释“组件化思维” 和 “原子化思维” 区别的文章;
  4. ACSS 官网 @雅虎
    这个思维最早应该是雅虎推出来的,最近他们有在推 React ACSS
  5. 关于HTML语义和前端架构 @大漠;
  6. 「译」CSS通用类和“关注点分离” @adamwathan;
  7. 「英」Styling React @SURVIVEJS;
  8. 「英」CSS最佳实践探讨 - Atomic CSS @smashingmagazine;

“”

关注下面的标签,发现更多相似文章
评论