层叠、优先级和继承
1. 层叠
CSS 本质上就是声明规则,浏览器根据这些规则去渲染页面。
当声明发生冲突时,层叠会依据三种规则去解决冲突:
- 样式表的来源:样式是从哪里来的。
- 选择器优先级:哪些选择器更重要。
- 源码顺序:样式在样式表里的声明顺序。
1.1 样式表的来源
- 通过 CSS 自定义的样式属于作者样式表,此外还有用户代理样式表,即浏览器默认样式。
- 用户代理样式表优先级低,作者样式表会覆盖它们。
说明
有些浏览器允许用户创建一个用户样式表,优先级介于作者样式表和用户代理样式表之间,用户样式表很少见。
- 用户代理样式在不同的浏览器中稍有差异。
!important
:在样式声明的后面,分号的前面加上!important
,该声明就会标记为重要的声明,该声明会当作更高优先级的来源。- 来源总体优先级:作者的
!important
> 作者 > 用户代理。
1.2 理解优先级
如果无法用来源解决冲突声明,浏览器会尝试检查它们的优先级。
1.2.1 行内样式
- 如果用 HTML 的
style
属性写的样式就是行内样式,只作用于当前元素。 - 行内样式会覆盖任何来自样式表或者
<style>
标签的样式(除了重要声明之外)。 - 行内样式没有选择器。
- 在样式表中给样式添加
!important
就会覆盖行内声明,但如果行内样式也使用了!important
标记,则无法被覆盖。实践中最好只在样式表中使用!important
。
1.2.2 选择器优先级
- 如果选择器的 ID 更多,则优先级更高。
- 如果 ID 选择器数量一样,那么拥有更多类的选择器胜出。
- 如果上述比较都一致,则拥有更多标签名的选择器胜出。
- 伪类选择器如
:hover
和属性选择器如[type="input"]
与一个类选择器优先级相同。通用选择器*
和组合器+
、>
、~
对优先级没影响。
1.3 源码顺序
如果两个声明的来源和优先级相同,其中一个声明在样式表中出现较晚,或者位于页面较晚引入的样式表中,则该声明胜出。
1.3.1 链接样式和源码顺序
给链接加伪类样式要按一定的顺序书写,否则后面的样式可能覆盖前面的样式,导致样式不起作用:
css
a:link {
color: blue;
text-decoration: none;
}
a:visited {
color: purple;
}
a:hover {
text-decoration: underline;
}
a:active {
color: red;
}
1.3.2 层叠值
- 按来源、优先级、源码顺序来解析元素的样式,最终胜出的属性声明就是层叠值。
- 元素的每个属性最多只有一个层叠值。
1.4 两条经验法则
- 选择器中尽量不使用 ID 选择器。
- 尽量不使用
!important
声明,因为它比 ID 选择器优先级更高,更难覆盖。
2. 继承
如果一个元素的某个属性没有层叠值,则可能会继承某个祖先元素的值。如通常会给 <body>
元素设置 font-family
,所有后代元素都会加上这个字体。
默认情况下,只有特定的一些属性能够继承:
- 跟文本相关的属性:
color
、font
、font-family
、font-size
、font-weight
、font-style
、line-height
、letter-spacing
、text-align
、text-indent
、text-transform
、white-space
以及word-spacing
。 - 列表属性:
list-style
、list-style-type
、list-style-position
、list-style-image
。 - 表格的边框属性:
border-collapse
、border-spacing
。
3. 特殊值
3.1 inherit 关键字
- 使用
inherit
关键字可以用继承替代一个层叠值,该元素会继承其父元素的值。 - 通常不会被继承的属性,可以通过
inherit
关键字强制继承。
css
.footer {
color: #666;
...
}
.footer a {
/* 页脚链接的颜色随页脚颜色而改变 */
color: inherit;
}
3.2 initial 关键字
- 使用
initial
关键字可以撤销作用于某元素的样式。 - 每个 CSS 属性都有默认值,将
initial
赋给某元素,会将其置为默认值。
css
.footer a {
/* 链接为黑色,在大多数浏览器中,黑色是 color 属性的初始值 */
color: initial;
}
4. 简写属性
简写属性是用于同时给多个属性赋值的属性。如:
font
:指定了font-style
、font-weight
、font-size
、font-height
及font-family
。background
:指定了background-color
、background-image
、background-size
、background-repeat
、background-position
、background-origin
、background-clip
、background-attachment
。border
:指定了border-width
、border-style
、border-color
,这几个属性也都是简写属性。
4.1 简写属性会覆盖其它样式
- 大部分简写属性可以省略一些值,不写的属性仍会隐式设置为初始值。这会默默覆盖在其它地方定义的样式。
font
属性尤其需要注意,要避免在<body>
元素的通用样式之外使用font
。
css
h1 {
font-weight: bold;
}
.title {
font: 32px Helvetica, Arial, snas-serif;
}
/* 后面 font 属性省略了 font-weight,会设置为默认 normal */
4.2 理解简写值的属性
很多简写属性的值遵循一定顺序,主要分为两种。
4.2.1 上、右、下、左
- 像
margin
、padding
这样的属性,以及为元素四条边指定值的边框属性,值得顺序都是顺时针的,从上方开始。 - 当只写了三个值时,左边和右边都会使用第二个值。
- 只写了两个值时,第一个用与上下,第二个值用于左右。
4.2.2 水平、垂直
- 有的属性只能设置两个方向的值,代表水平和垂直方向(笛卡尔网格),此时第一个值代表水平(左右),第二个值代表垂直(上下)。
- 这些属性包括
background-position
、box-shadow
、text-shadow
等。
总结:如果属性需要指定从一个点出发的两个方向的值,就想想水平和垂直,如果需要指定一个元素的四个方向的值,就想想顺时针。