层叠样式表中最基本的一个方面可能就是层叠——冲突的声明要通过这个层叠过程排序,并由此确定最终的文档表示。这个过程的核心是选择器及其相关声明的特殊性,以及继承机制。
特殊性
对于每个规则,用户代理会计算选择器的特殊性,并将这个特殊性附加到规则中的各个声明。如果一个元素有两个或多个冲突的属性声明,那么有最高特殊性的声明就会胜出。
选择器的特殊性由选择器本身的组件确定。特殊性值表述为4个部分,如:0,0,0,0。一个选择器的具体特殊性如下确定:
对于选择器中给定的各个ID属性值,加0,1,0,0。
对于选择器中给定的各个类属性值,属性选择或伪类,加0,0,1,0。
对于选择器中给定的各个元素和伪元素,加0,0,0,1。
内联样式,加1,0,0,0。
结合符和通配符选择器对特殊性没有任何贡献
h1{color:red;}/* specifity = 0,0,0,1 */
p em{color:purple;}/* specifity = 0,0,0,2 */
.grape{color:purple;}/* specifity = 0,0,1,0 */
*.bright{color:yellow;}/* specifity = 0,0,1,0 */
p.bright em.dark{color:maroon;}/* specifity = 0,0,2,2 */
#id216{color:blue;}/* specifity = 0,1,0,0 */
div#sidebar *[href]{color:silver;}/* specifity = 0,1,1,1 */
h1+p{color:black;font-style:italic;}/* specifity = 0,0,0,2 */
<h1 style="color:green;">Green</h1> /* specifity = 1,0,0,0*/
重要性
CSS允许在这些声明的结束分号之前插入 !important 来标志。
p.dark {color:#333 !important; background: white;}
标志为!important的声明并没有特殊的特殊性值,不过要与非重要声明分开考虑。实际上,所有!important声明会分组在一起,重要声明的特殊性冲突会在重要声明内部解决,而不会与非重要声明相混。如果一个重要声明和一个非重要声明冲突,胜出的总是重要声明。
继承
样式不仅应用到指定的元素,还会应用到它的后代元素。
/*
将声明color :gray;应用到ul元素时,这个元素会采用该声明。这个值再沿着树向下传播到后代元素,并一直继续,直到再没有更多的后代元素继承这个值为止。值绝对不会向上传播,也就是说,元素不会把值向上传递到其祖先。
*/
/*
注意:在HTML中,对于向上传播规则有一个例外:应用到body元素的背景样式可以传递到html元素(html是文档的根元素),相应地可以定义其画布。
*/
ul {
color: red;
}
一般地,大多数框模型属性(包括外边距、内边距、背景和边框)不能继承。
继承的值根本没有特殊性,甚至连0特殊性都没有。
只要id为toolbar的元素只包含纯文本而不包含其他内容,这就能正常起作用。不过,如果这个元素中的文本都是超链接(a元素),用户代理的超链接样式就会占上风。在一个Web浏览器中,这意味着它们的颜色很可能是蓝色,因为浏览器的样式表可能包含以下规则:
a:link {color: blue;}
为克服这个问题,必须如下声明:
#toolbar {color: white; background: black;}
#toolbar a:link {color: white;}通过向工具条中的a元素直接指定规则才可以覆盖默认的规则了。
而通配选择器具有0特殊性,所以一旦应用了通配选择器,它就会覆盖继承的值,所以通配选择器往往有一种短路继承的效果。这说明不加区别的使用通配选择器可能存在奇怪的问题。
层叠
- 按显式权重对应用到该元素的所有声明排序。标志!important的规则的权重要高于没有!important标志的规则。
- 按来源对应用到给定元素的所有声明排序。共有3种来源:创作人员、读者和用户代理。正常情况下,创作人员的样式要胜过读者的样式。有!important标志的读者样式要强干所有其他样式,这包括有!important标志的创作人员样式。创作人员样式和读者样式都比用户代理的默认样式要强。
- 读者的!important样式
- 创作者的!important样式
- 创作者的正常样式
- 读者的正常样式
- 用户代理声明的样式
- 按特殊性对应用到给定元素的所有声明排序。有较高特殊性的元素权重要大于有较低特殊性的元素。
- 按出现顺序对应用到给定元素的所有声明排序。一个声明在样式表或文档中越后出现,它的权重就越大。如果样式表中有导入的样式表,一般认为出现在导入样式表中的声明在前,主样式表中的所有声明在后。