在参与规模庞大、历时漫长且参与人数众多的项目时,所有开发者遵守如下规则极为重要:
为了实现这一目标,我们要采用诸多方法。
本文档第一部分将探讨语法、格式以及分析 CSS 结构;第二部分将围绕方法论、思维框架以及编写与规划 CSS 的看法。
CSS 文档分析
无论编写什么文档,我们都应当维持统一的风格,包括统一的注释、统一的语法与统一的命名规范。
总则
将行宽控制在 80 字节以下。渐变(gradient)相关的语法以及注释中的 URL 等可以算作例外,毕竟这部分我们也无能为力。
我倾向于用 4 个空格而非 Tab 缩进,并且将声明拆分成多行。
单一文件与多文件
有人喜欢在一份文件文件中编写所有的内容,而我在迁移至 Sass 之后开始将样式拆分成多个小文件。这都是很好的做法。无论你选择哪种,下文的规则都将适用,而且如果你遵守这些规则的话你也不会遇到什么问题。这两种写法的区别仅仅在于目录以及区块标题:
目录
在 CSS 的开头,我会维护一份目录,就像这样:
/*————————————*\$CONTENTS\*————————————*//** * CONTENTS…………You’re reading it! * RESET……………Set our reset defaults * FONT-FACE………..Import brand font files */
这份目录可以告诉其他开发者这个文件中具体含有哪些内容。这份目录中的每一项都与其对应的区块标题相同。
如果你在维护一份单文件 CSS,对应的区块将也在同一文件中。如果你是在编写一组小文件,那么目录中的每一项应当对应相应的 @include 语句。
区块标题
目录应当对应区块的标题。如下:
/*————————————*\$RESET\*————————————*/
区块标题前缀$可以让我们使用 [Cmd|Ctrl]+F 命令查找标题名时将搜索范围限制在区块标题中。
如果你在维护一份大文件,那么在区块之间空 5 行,如下:
/*————————————*\$RESET\*————————————*/[Ourresetstyles]/*————————————*\$FONT-FACE\*————————————*/
在大文件中快速翻动时这些大块的空档有助于区分区块。
如果你在维护多份以 include 连接的 CSS 的话,在每份文件头加上标题即可,不必这样空行。
代码顺序
尽量按照特定顺序编写规则,这将确保你充分发挥 CSS 中第一个C的意义:cascade,层叠。
一份规划良好的 CSS 应当按照如下排列:
如此一来,当你依次编写 CSS 时,每个区块都可以自动继承在它之前区块的属性。这样就可以减少代码相互抵消的部分,减少某些特殊的问题,组成更理想的 CSS 结构。
关于这方面的更多信息,强烈推荐 Jonathan Snook 的SMACSS。
CSS 样式集分析[selector]{[property]:[value];[<- Declaration ->]}[选择器]{[属性]:[值];[<- 声明 ->]}
编写 CSS 样式时,我习惯遵守这些规则:
例如:
.widget{padding:10px;border:1px solid #BADA55;background-color:#C0FFEE;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.widget-heading{font-size:1.5rem;line-height:1;font-weight:bold;color:#BADA55;margin-right:-10px;margin-left: -10px;padding:0.25em;}
我们可以发现,.widget-heading是.widget的子元素,因为前者的样式集比后者多缩进了一级。这样通过缩进就可以让开发者在阅读代码时快速获取这样的重要信息。
我们还可以发现.widget-heading的声明是根据其相关性排列的:.widget-heading是行间元素,所以我们先添加字体相关的样式声明,接下来是其它的。
以下是一个没有拆分成多行的例子:
.t10 { width:10% }.t20 { width:20% }.t25 { width:25% }/* 1/4 */.t30 { width:30% }.t33 { width:33.333% } /* 1/3 */.t40 { width:40% }.t50 { width:50% }/* 1/2 */.t60 { width:60% }.t66 { width:66.666% } /* 2/3 */.t70 { width:70% }.t75 { width:75% }/* 3/4*/.t80 { width:80% }.t90 { width:90% }
在这个例子(来自)中,将 CSS 放在一行内可以使得代码更紧凑。
命名规范
一般情况下我都是以连字符(-)连接 class 的名字(例如.foo-bar而非.foo_bar或.fooBar),不过在某些特定的时候我会用 BEM(Block, Element, Modifier)命名法。
BEM 命名法可以使得选择器更规范,更清晰,更具语义。
该命名法按照如下格式:
.block{}.block__element{}.block–modifier{}
其中:
打个比方:
.person{}.person–woman{}.person__hand{}.person__hand–left{}.person__hand–right{}
这个例子中我们描述的基本元素是一个人,然后这个人可能是一个女人。我们还知道人拥有手,这些是人体的一部分,而手也有不同的状态,如同左手与右手。
这样我们就可以根据亲元素来划定选择器的命名空间并传达该选择器的职能,例如根据这个选择器是一个子元素(__)还是其亲元素的不同状态(–)。
由此,.page-wrapper是一个独立的选择器。这是一个符合规范的命名,因为它不是其它元素的子元素或其它状态;然而.widget-heading则与其它对象有关联,它应当是.widget的子元素,所以我们应当将其重命名为.widget__heading。
BEM 命名法虽然不太好看,而且相当冗长,但是它使得我们可以通过名称快速获知元素的功能和元素之间的关系。与此同时,BEM 语法中的重复部分非常有利于 gzip 的压缩算法。
无论你是否使用 BEM 命名法,你都应当确保 class 命名得当,力保一字不多、一字不少;将元素命名抽象化以提高复用性(例如.ui-list,.media)。子元素的命名则要尽量精准(例如.user-avatar-link)。不用担心 class 名的数量或长度,因为写得好的代码 gzip 也能有效压缩。
HTML 中的 class
为了确保易读性,在 HTML 标记中用两个空格隔开 class 名,例如:
<div>
增加的空格应当可以使得在使用多个 class 时更易阅读与定位。
JavaScript 钩子
切勿将标记 CSS 样式的 class 用作 JavaScript 钩子。把 JS 行为与样式混在一起将无法对其分别处理。
没有朋友的人生是孤独的,不完整的,可是,因为生活的忙碌,