引言
写 CSS 最让人抓狂的时刻,莫过于:明明写了样式,页面上却毫无变化。或者改了一个地方,另一个地方莫名其妙跟着变了。这背后是 CSS 的层叠和优先级机制在起作用。不理解它,你只能靠反复试错;理解了它,你就能准确预测哪条规则会赢。这篇文章只讲这一个问题。
一、什么是层叠
CSS 全称里的第一个 C,就是层叠。它的意思是:多条规则可以同时作用于同一个元素,浏览器按一套规则决定最终用哪条。
为什么需要层叠?因为样式来源很多:浏览器默认样式、你自己写的样式、第三方库的样式、用户自定义的样式。它们可能都指向同一个元素,必须有个仲裁机制。
层叠不是简单的"后写的覆盖先写的",而是一套多因素综合判断的体系。优先级只是其中一环。
二、优先级的基本规则
优先级,衡量的是选择器的"具体程度"。选择器越具体,优先级越高。
大致可以这样理解:
行内样式最高,直接写在元素上的样式,优先级压过大多数外部规则。
标识选择器次之,针对某个唯一标识的规则,比针对一类元素的规则更具体。
类、属性、伪类选择器再次之。
元素选择器更低。
通用选择器最低。
组合选择器时,优先级是各部分累加的。选择器写得越长越具体,优先级通常越高。
三、优先级相同的时候
如果两条规则优先级相同,那就看谁写在后面。后写的赢。
这是很多人熟悉的"后来居上"。但要注意,这个规则只在优先级相同时生效。如果一条规则优先级更高,哪怕它写在前面,也会赢。
还有一个因素:来源。不同来源的样式,层叠顺序不同。浏览器默认样式优先级最低,作者写的样式更高,用户自定义的样式在某些情况下可以覆盖作者样式。不过日常开发中,主要打交道的还是作者样式内部的优先级。
四、为什么样式不生效
样式不生效,通常有几种原因。
第一,优先级不够。 你写的规则被另一条更具体的规则压住了。比如你用类选择器写,但别处用标识选择器写了同样的属性,后者赢。
第二,被后面的规则覆盖。 优先级相同,但你的规则写在前面,后面的规则把它盖了。
第三,选择器根本没匹配上。 类名拼错、层级写错、状态没触发,规则压根没作用到元素上。这种问题用开发者工具一查便知。
第四,属性被继承或初始值覆盖。 有些属性不继承,你没显式设置,它就用默认值,看起来像"没生效"。
第五,被更高来源覆盖。 比如浏览器默认样式或某些库的强制样式压过了你的规则。
排查时,开发者工具会显示每条规则的来源和优先级,被划掉的规则就是没生效的。这是定位问题最快的方式。
五、提升优先级的常见手段
加具体度。 把选择器写得更具体一点,比如多加一层父级、多加一个类。但不要滥用,选择器过长会难维护。
调整顺序。 优先级相同时,把规则往后放。
使用强制标记。 有一种写法可以强制某条声明拥有最高优先级,压过一切。但它是一把双刃剑:用多了会导致样式难以覆盖,别人想改都改不动。应该作为最后手段,而不是常规操作。
合理组织样式结构。 从根本上说,减少优先级冲突的最好办法,是规划好样式的层次:基础样式、组件样式、页面样式各司其职,避免互相打架。
六、继承与层叠的关系
有些属性会继承:父元素设了,子元素自动拥有。比如字体、颜色、行高。
继承来的样式,优先级非常低。任何直接作用于元素本身的规则,都能覆盖继承来的值。
理解继承,能解释一些"我没设这个属性,它怎么有这个效果"的现象。也能帮你用更少的代码实现统一的样式,比如在根元素上设字体,全站继承。
七、怎么写出好维护的样式
第一,保持选择器简短。 能用一层类选择器解决的,不要套三层。选择器越短,优先级越可控,越容易被覆盖。
第二,避免滥用强制标记。 它会让样式体系失去层次,后期改动极其痛苦。
第三,约定命名规范。 用清晰的类名表达用途,减少样式之间的意外冲突。
第四,分层组织。 把重置样式、基础样式、布局样式、组件样式分开管理,每层职责明确,层叠关系就清晰。
第五,善用开发者工具。 遇到样式问题,先看工具里哪条规则赢了、为什么赢,而不是盲目加具体度。
八、总结
层叠是 CSS 多规则仲裁的机制,优先级衡量选择器的具体程度,相同优先级看先后顺序。样式不生效,通常是优先级不够、被覆盖、没匹配上或来源被压。理解这套规则,你就能准确预测哪条样式会生效,也能写出层次清晰、易于维护的样式体系。这是 CSS 从"能写"到"写得明白"的关键一步。