# 适用性深度
学习CSS时,我们知道选择器可以选择对应元素,然后编写对应的样式。CSS不断成长,选择器也不断增加,我们发挥余地也越来越大。不过,我们设置的样式越多,CSS和HTML之间的联系就越紧密。
我们来看一个典型的CSS代码块,你可以在某个站点上能够找到。
/* 我们是如何将我们CSS和HTML紧密联系在一起 */
#sidebar div {
border: 1px solid #333;
}
#sidebar div h3 {
margin-top: 5px;
}
#sidebar div ul {
margin-bottom: 5px;
}
看上面例子,你可能会发现,代码对HTML的结构是有一些预期的:sidebar
应该有几个部分,而每个部分中可能有一个标题和一个无序的列表。如果站点不经常改变,上述CSS样式可能是OK的。比如我已经两年没有对我博客的设计有任何改变了,因为博客的扩展需求不大。但如果我尝试使用这种方法在更大的网站上,这个网站改变十分频繁,并且有很多不同的代码需求,那可能我就会遇到麻烦了。我可能需要添加更多有更复杂的选择器的规则,那时我可能会发现自己处于维护噩梦中。
我哪里弄错了呢?这个CSS例子中主要有两点需要特别关注的:
- 十分依赖定义好的HTML结构
- 选择器应用HTML结构的深度过深了
# 最小化深度
HTML是一颗有父节点和子节点的树。适用性的深度是特定规则影响的层次数量。例如,body.article > #main > #content > #intro > p > b
的适用性深度是6,如果我们把它写成.article #intro b
,深度还是相同,同样是6。
这样的深度的问题主要是它使得我们对特定HTML结构的依赖更深了。页面上的组件不能被简单地转移使用。如果我们回顾下sidebar
的例子,想下,我们怎么样在页面的另外部分(比方说footer
)创建一个这样的模块?我们必须重复这些规则!
/* 规则的重复 */
#sidebar div, #footer div {
border: 1px solid #333;
}
#sidebar div h3, #footer div h3 {
margin-top: 5px;
}
#sidebar div ul, #footer div ul {
margin-bottom: 5px;
}
根节点在div
处,我们从这里创建一个新的类,创建我们的样式。
/* 简化规则 */
.pod {
border: 1px solid #333;
}
.pod > h3 {
margin-top: 5px;
}
.pod > ul {
margin-bottom: 5px;
}
pod
是一个容器,它仍然依赖特殊的HTML结构,但是其深度比我们之前的浅多了。但相对的,我们必须在页面的元素上重复pod
类名。而之前我们只有两个元素的ID。当然,我们也要避免做在每个段落上添加类名这样的傻事儿。
适用性深度较浅还有一个好处:可以使得把模块转换为动态内容模板更加容易。例如,在雅虎,我们使用Mustache
来满足我们的大部分模板需求。下面展示了我们如何为这些pod
生成模板。
<!-- 一个Mustache模板 -->
<div class="pod">
<h3>{{heading}}</h3>
<ul>
{{#items}}
<li>{{item}}</li>
{{/items}}
</ul>
</div>
上述例子,我们正努力在维护性,性能,可读性上取得平衡。虽然在HTML中,深度越深意味着类越少(多类症
不容易发生),但是它增加了维护成本,减少了可读性。而且你也没必要在所有地方都加上类。在h3或是ul上添加类名是不太必要的,除非你想构造更加灵活的系统。
最后一个例子更进一步讲,是一个普遍的设计模式。就是一个带有header
和body
的容器(有时,还会有一个footer
)。我们在例子中已经有了一个ul
,但在其他例子中,可能会是ol
或者是div
。
我们可能还是为每个类重复规则。
/* 规则重复 */
.pod > ul, .pod > ol, .pod > div {
margin-bottom: 5px;
}
也可以为pod
的body
添加类。
/* 用类来简化 */
.pod-body {
margin-bottom: 5px;
}
用模块的命名规则,我们都不需要标定.pod
。我们可以直观地看到.pod-body
和pod
模块是关联在一起的,而从代码层面来说,这照样可以很好地工作。
<!-- Mustache模板的例子 -->
<div class="pod">
<h3>{{heading}}</h3>
<ul class="pod-body">
{{#items}}
<li>{{item}}</li>
{{/items}}
</ul>
</div>
这个微小的更改使得适用性深度达到最小。而单个选择器也意味着我们可以避免一些潜在的特殊问题。不管怎么说,都是多赢的方法!