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