Skip to content

Commit

Permalink
130625
Browse files Browse the repository at this point in the history
  • Loading branch information
chadluo committed Jun 25, 2013
1 parent 9b8c034 commit 7a19b33
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 580 deletions.
76 changes: 38 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

为了实现这一目标,我们要采用诸多方法。

本文档第一部分将探讨语法、格式以及 CSS 分析;第二部分将从方法论、思维框架、以及编写与规划 CSS 样式的态度入手
本文档第一部分将探讨语法、格式以及 CSS 分析;第二部分将从方法论、思维框架以及编写与规划 CSS 的态度入手

## 目录

Expand Down Expand Up @@ -43,7 +43,7 @@
* 选择器继承
* `!important`
* 魔数与绝对比例
* 条件判断 CSS
* 条件判断
* Debugging
* 预处理

Expand All @@ -57,17 +57,17 @@

### 总则

尽量将行宽控制在 80 字节以下,除了渐变(gradient)相关的语法以及注释中的 URL,毕竟这部分我们也无能为力。
尽量将行宽控制在 80 字节以下。渐变(gradient)相关的语法以及注释中的 URL 等可以算作例外,毕竟这部分我们也无能为力。

我倾向于用 4 个空格而非 Tab 缩进,并且将样式拆分成多行
我倾向于用 4 个空格而非 Tab 缩进,并且将声明拆分成多行

### 单一文件与多文件

有些人喜欢将样式写成一个大文件,这并不赖,而且如果你按照下文的规则来编写的话也不会遇到什么问题。我在迁移至 Sass 之后,开始将样式拆分成众多小文件。这也不赖……无论你采用什么方式,下文中的规则都将适用。唯一的区别在于目录以及区块标题
有些人喜欢将样式写成一个大文件,这并不赖,而且如果你按照下文的规则来编写的话也不会遇到什么问题。我在迁移至 Sass 之后,开始将样式拆分成众多小文件。这也不赖无论你采用什么方式,下文中的规则都将适用。这两种写法仅仅在目录以及区块标题上有所差异

### 目录

在样式表的开头,我会写一份目录,例如:
在 CSS 的开头,我会写一份目录,例如:

/*------------------------------------*\
$CONTENTS
Expand All @@ -78,9 +78,9 @@
* FONT-FACE...........Import brand font files
*/

这份目录可以告诉其他开发者这份文档中具体含有哪些内容。这份目录中的每一项都与其对应的区块标题相同。
这份目录可以告诉其他开发者这个文件中具体含有哪些内容。这份目录中的每一项都与其对应的区块标题相同。

如果你在维护一份规模较大的单文件样式表,对应的区块将也在同一文件中。如果你是在编写一组小文件,那么目录中的每一项应当对应其相应的 @include 语句。
如果你在维护一份规模较大的单文件 CSS,对应的区块将也在同一文件中。如果你是在编写一组小文件,那么目录中的每一项应当对应相应的 @include 语句。

### 区块标题

Expand All @@ -90,7 +90,7 @@
$RESET
\*------------------------------------*/

区块标题前缀 `$` 可以让我们使用([Cmd|Ctrl]+F)命令查找 `$[SECTION-NAME]` **将搜索范围限制在区块标题中**
区块标题前缀 `$` 可以让我们使用([Cmd|Ctrl]+F)命令查找 `$[SECTION-NAME]`,同时 **将搜索范围限制在区块标题中**

如果你在维护一份大文件,那么在区块之间空 5 行,如下:

Expand All @@ -111,21 +111,21 @@

在大文件中快速翻动时这些大块的空档有助于区分区块。

如果你在维护多份、以 @include 连接的样式表的话,在每份文件头加上标题即可,不必这样空行。
如果你在维护多份、以 @include 连接的 CSS 的话,在每份文件头加上标题即可,不必这样空行。

## 顺序

尽量按照特定顺序编写规则,这将确保你充分发挥 CSS 缩写中第一个 <i>C</i> 的意义:cascade,层叠。

一份规划良好的样式表应当按照如下排列
一份规划良好的 CSS 应当按照如下排列

1. **Reset** 万物之根源
2. **元素类型** 没有设置 class 的 `h1``ul`
3. **对象以及抽象内容** 最一般、最基础的设计模式
4. **子元素** 由对象延伸出来的所有拓展及其子元素
5. **修补** 针对异常状态

如此一来,当你依次编写 CSS 时,每个区块都可以自动继承在它之前区块的属性。这样就可以减少代码相互抵消的部分,减少某些特殊的问题,构成设计更理想的样式表结构
如此一来,当你依次编写 CSS 时,每个区块都可以自动继承在它之前区块的属性。这样就可以减少代码相互抵消的部分,减少某些特殊的问题,构成设计更理想的 CSS 结构

关于这方面的更多信息,强烈推荐 Jonathan Snook 的 [SMACSS](http://smacss.com)

Expand All @@ -147,11 +147,11 @@
* 缩进 4 空格;
* 声明拆分成多行;
* 声明以相关性顺序排列,而非字母顺序;
* 有前缀的声明适当缩进,使得其值对齐
* 缩进样式以便反映 DOM;
* 有前缀的声明适当缩进,对齐其值
* 缩进样式从而反映 DOM;
* 保留最后一条声明结尾的分号。

上例子
例如

.widget{
padding:10px;
Expand Down Expand Up @@ -197,7 +197,7 @@

一般情况下我都是以连字符(-)连接 class 的名字(例如 `.foo-bar` 而非 `.foo_bar``.fooBar`),不过在某些特定的时候我会用 BEM(Block, Element, Modifier)命名法。

<abbr title="Block, Element, Modifier">BEM</abbr> 命名法可以使得选择器更规范,更透明,更具语义。
<abbr title="Block, Element, Modifier">BEM</abbr> 命名法可以使得选择器更规范,更清晰,更具语义。

该命名法按照如下格式:

Expand All @@ -208,7 +208,7 @@
其中:

* `.block` 代表某个基本的抽象元素;
* `.block__element` 代表 `.block` 整体的一个子元素
* `.block__element` 代表 `.block` 这一整体的一个子元素
* `.block--modifier` 代表 `.block` 的某个不同状态。

打个比方:
Expand All @@ -219,13 +219,13 @@
.person__hand--left{}
.person__hand--right{}

这个例子中我们描述的最基本元素是一个人,这个人可能是一个女人。我们还知道人拥有手,这些是人体的一部分,而手也有不同的状态,如同左手与右手。
这个例子中我们描述的最基本元素是一个人,然后这个人可能是一个女人。我们还知道人拥有手,这些是人体的一部分,而手也有不同的状态,如同左手与右手。

这样我们就可以根据亲元素来规定选择器的命名空间并传达该选择器的职能,它是一个子元素(`__`)还是不同状态(`--`)?

由此,`.page-wrapper` 是一个单独的选择器,这是一个符合规范的命名,而且它也不是其它元素的子元素或其它状态;然而 `.widget-heading` 则与其它对象有关联,它应当是 `.widget` 的子元素,所以我们应当将其重命名为 `.widget__heading`
由此,`.page-wrapper` 是一个独立的选择器。这是一个符合规范的命名,因为它不是其它元素的子元素或其它状态;然而 `.widget-heading` 则与其它对象有关联,它应当是 `.widget` 的子元素,所以我们应当将其重命名为 `.widget__heading`

BEM 命名法虽然不太好看,而且相当冗长,但是它使得我们可以通过名称快速获知元素的功能和元素之间的关系。与此同时,BEM 语法中的重复部分非常有利于压缩算法
BEM 命名法虽然不太好看,而且相当冗长,但是它使得我们可以通过名称快速获知元素的功能和元素之间的关系。与此同时,BEM 语法中的重复部分非常有利于 gzip 的压缩算法

无论你是否使用 BEM 命名法,你都应当确保 class 命名得当,力保一字不多、一字不少;将元素命名抽象化以提高复用性(例如 `.ui-list``.media`)。由此延伸出去的元素命名则要尽量精准(例如 `.user-avatar-link`)。不用担心 class 名的数量或长度,因为写得好的代码 gzip 也能有效压缩。

Expand Down Expand Up @@ -282,20 +282,20 @@ BEM 命名法虽然不太好看,而且相当冗长,但是它使得我们可


/**
* 这部分是块状注释
* 这是一个文档块(DocBlock)风格的注释
*
* 这部分是描述更详细、篇幅更长的注释。当然,我们要把行宽控制在 80 字以内。
* 这里开始是描述更详细、篇幅更长的注释正文。当然,我们要把行宽控制在 80 字以内。
*
* 我们可以在注释中嵌入 HTML 标记,而且这也是个不错的办法:
*
<div class=foo>
<p>Lorem</p>
</div>
*
* 如果是注释内嵌的标记的话,在它前面不加星号,否则容易被复制进去
* 如果是注释内嵌的标记的话,在它前面不加星号,否则会被复制进去
*/

在注释中应当尽量详细描述代码,因为对你来说昭然若揭的内容对其他人可能并非如此。每写一部分代码就要专门写注释以详解。
在注释中应当尽量详细描述代码,因为对你来说清晰易懂的内容对其他人可能并非如此。每写一部分代码就要专门写注释以详解。

### 注释的拓展用法

Expand All @@ -309,7 +309,7 @@ BEM 命名法虽然不太好看,而且相当冗长,但是它使得我们可

你应当避免过分修饰选择器,例如如果你能写 `.nav{}` 就尽量不要写 `ul.nav{}`。过分修饰选择器将影响性能,影响 class 复用性,增加选择器私有度。这些都是你应当竭力避免的。

不过有时你可能希望告诉其他开发者 class 的使用范围。以 `.product-page` 为例,这个 class 看起来像是一个根容器,可能是 `html` 或者 `body` 元素,但是仅凭 `.product-page` 就无法判断
不过有时你可能希望告诉其他开发者 class 的使用范围。以 `.product-page` 为例,这个 class 看起来像是一个根容器,可能是 `html` 或者 `body` 元素,但是仅凭 `.product-page` 则无法判断

我们可以在选择器前加上准修饰(即将前面的类型选择器注释掉)来描述我们规划的 class 作用范围:

Expand Down Expand Up @@ -369,9 +369,9 @@ BEM 命名法虽然不太好看,而且相当冗长,但是它使得我们可

## 编写新组件

编写新组件时,要在着手处理 CSS **之前** 写好标记部分。这可以令你准确判断哪些 CSS 属性可以继承,避免重复浪费。
编写新组件时,要在着手处理 CSS **之前** 写好 HTML 部分。这可以令你准确判断哪些 CSS 属性可以继承,避免重复浪费。

先写标记的话,你就可以关注数据、内容与语义,在这之后再施加需要的 class 和 CSS 样式。
先写标记的话,你就可以关注数据、内容与语义,在这之后再添加需要的 class 和 CSS 样式。

## 面向对象 CSS

Expand All @@ -383,7 +383,7 @@ BEM 命名法虽然不太好看,而且相当冗长,但是它使得我们可
.room--bedroom{}
.room--bathroom{}

我们在屋子里有许多房间,它们都有共同的特点:他们都有地板、天花板、墙壁和门。这些共享的部分我们可以放到一个抽象的 `.room{}` class 中。不过我们还有其它与众不同的房间:一个厨房可能有地砖,卧室可能有地毯,洗手间可能没有窗户但是卧室会有,每个房间的墙壁颜色也许也会不一样。面向对象 CSS 的思路使得我们把相同部分抽象出来组成结构部分,然后用更具体的 class 来拓展这些特征并添加特殊的处理方法。
我们在屋子里有许多房间,它们都有共同的特点:它们都包含地板、天花板、墙壁和门。这些共享的部分我们可以放到一个抽象的 `.room{}` class 中。不过我们还有其它与众不同的房间:一个厨房可能有地砖,卧室可能有地毯,洗手间可能没有窗户但是卧室会有,每个房间的墙壁颜色也许也会不一样。面向对象 CSS 的思路使得我们把相同部分抽象出来组成结构部分,然后用更具体的 class 来拓展这些特征并添加特殊的处理方法。

所以比起编写大量的特殊模块,应当努力找出这些模块中重复的设计模式并将其抽象出来,写成一个可以复用的 class,将其用作基础然后编写其它拓展模块的特殊情形。

Expand All @@ -393,11 +393,11 @@ BEM 命名法虽然不太好看,而且相当冗长,但是它使得我们可

所有组件都不要声明宽度,而由其亲元素或格栅系统来决定。

**坚决不要** `height`。高度应当仅仅用于尺寸已经固定的东西,例如图片和 CSS Sprite。在 `p``ul``div` 等元素上不应当声明高度。如果需要的话可以写 `line-height`,这个更加灵活。
**坚决不要** 声明高度。高度应当仅仅用于尺寸已经固定的东西,例如图片和 CSS Sprite。在 `p``ul``div` 等元素上不应当声明高度。如果需要的话可以写 `line-height`,这个更加灵活。

格栅系统应当当作书架来理解。是它们容纳内容,而不是把它们本身当成内容装起来,正如你总是先搭起书架再把东西放进去。比起声明它们的尺寸,把格栅系统和元素的其它属性分来开处理更有助于布局,也使得我们的前端工作更高效。
格栅系统应当当作书架来理解。是它们容纳内容,而不是把它们本身当成内容装起来,正如你先搭起书架再把东西放进去。比起声明它们的尺寸,把格栅系统和元素的其它属性分来开处理更有助于布局,也使得我们的前端工作更高效。

你在格栅系统上不应当添加任何样式,他们仅仅是为布局而用。在格栅系统之中再添加样式。在格栅系统中任何情况下都不要添加盒模型相关属性。
你在格栅系统上不应当添加任何样式,他们仅仅是为布局而用。在格栅系统内部再添加样式。在格栅系统中任何情况下都不要添加盒模型相关属性。

## UI 尺寸

Expand All @@ -421,8 +421,8 @@ BEM 命名法虽然不太好看,而且相当冗长,但是它使得我们可
## 简写

**CSS 简写应当谨慎使用。**

编写像 `background:red;` 这样的属性的确很省事,但是你这么写的意思其实是同时声明 `background-image:none; background-position:top left; background-repeat: repeat; background-color:red;`。虽然大多数时候这样不会出什么问题,但是哪怕只有一次出问题就该考虑要不要放弃简写了。这里应当将其改为 `background-color:red;`
编写像 `background:red;` 这样的属性的确很省事,但是你这么写的意思其实是同时声明 `background-image:none; background-position:top left; background-repeat: repeat; background-color:red;`。虽然大多数时候这样不会出什么问题,但是哪怕只出一次问题就值得考虑要不要放弃简写了。这里应当将其改为 `background-color:red;`

类似的,像 `margin:0;` 这样的声明的确简洁清爽,但是还是应当 **尽量写清楚**。如果你只是想修改底边的 `margin`,最好具体一些,写成 `margin-bottom:0;`

Expand All @@ -446,7 +446,7 @@ Class 的优势在于复用性,而且私有度也并不高。私有度非常

通过页面元素位置而定位的选择器并不理想。例如 `.sidebar h3 span{}` 这样的选择器就是定位过于依赖相对位置,所以很难把 span 移到 h3 和 sidebar 外面并保持其样式。

太长的选择器将会影响性能。选择器结构越复杂(如 `.sidebar h3 span` 为三层,`.content ul p a` 是四层),浏览器的消耗就越大。
结构复杂的选择器将会影响性能。选择器结构越复杂(如 `.sidebar h3 span` 为三层,`.content ul p a` 是四层),浏览器的消耗就越大。

尽量使得样式不依赖于其定位,尽量保持选择器简洁清晰。

Expand All @@ -464,15 +464,15 @@ Class 的优势在于复用性,而且私有度也并不高。私有度非常

### 选择器性能

虽然浏览器性能日渐提升,渲染 CSS 速度越来越快,但是你还是应当关注效率。简单说来,不用嵌套的选择器,不要把全局选择器`*{}`)用作核心选择器,避免使用日渐复杂的 CSS3 新选择器可以避免这样的问题。
虽然浏览器性能日渐提升,渲染 CSS 速度越来越快,但是你还是应当关注效率。使用间断、没有嵌套的选择器,不把全局选择器`*{}`)用作核心选择器,避免使用日渐复杂的 CSS3 新选择器可以避免这样的问题。

译注,核心选择器:浏览器解析选择器为从右向左的顺序,最右端的元素是样式生效的元素,是为核心选择器。

## 使用 CSS 选择器的目的

比起努力运用选择器定位到某元素,更好的办法是直接给你想要添加样式的元素直接添加一个 class。我们以 `.header ul{}` 这样一个选择器为例。

假定这个 `ul` 是这个网站的全站导航,它位于 header 中,而且目前为止是 header 中唯一的 `ul` 元素。`.header ul{}` 的确可以生效,但是这样并不是好方法,它很容易过时,而且非常晦涩。如果我们在 header 中再添加一个 `ul` 的话,它就会套用我们给这个导航部分写的样式,哪怕我们设想的不是这个效果。这意味着我们要么要重构许多代码或者给后面的 `ul` 新写许多样式来抵消之前的影响。
假定这个 `ul` 就是这个网站的全站导航,它位于 header 中,而且目前为止是 header 中唯一的 `ul` 元素。`.header ul{}` 的确可以生效,但是这样并不是好方法,它很容易过时,而且非常晦涩。如果我们在 header 中再添加一个 `ul` 的话,它就会套用我们给这个导航部分写的样式,哪怕我们设想的不是这个效果。这意味着我们要么要重构许多代码,要么给后面的 `ul` 新写许多样式来抵消之前的影响。

你的选择器必须符合你要给这个元素添加样式的原因。思考一下, **「我定位到这个元素,是因为它是 `.header` 下的 `ul`,还是因为它是我的网站导航?」**这将决定你应当如何使用选择器。

Expand Down Expand Up @@ -500,9 +500,9 @@ Class 的优势在于复用性,而且私有度也并不高。私有度非常

你在 CSS 中留下的每一个数字,都是你许下而不愿遵守的承诺。

## 条件判断样式表
## 条件判断

专门为 IE 写的样式基本上都是可以避免的,唯一需要为 IE 专门处理的是为了处理 IE 不支持的内容(例如 PNG)。
专门为 IE 写的样式基本上都是可以避免的,唯一需要为 IE 专门处理的是为了处理 IE 不支持的内容(例如 PNG)。

简而言之,如果你重构 CSS 的话,所有的布局和盒模型都不用额外兼容 IE。也就是说你基本上不用 `<!--[if IE 7]> element{ margin-left:-9px; } < ![endif]-->` 或者类似的兼容 IE 的写法。

Expand Down
Loading

0 comments on commit 7a19b33

Please sign in to comment.