# 特指度和层叠 Specificity and the Cascade
# 特指度
选择符的特指度由选择符本身的组成部分决定。一个特指度值由四部分组成,比如 0, 0, 0, 0 。
特指度是从左向右比较的。
- 选择符中每个 ID 选择符,加 0, 1, 0, 0
- 每个类选择符,属性选择符,伪类,加 0, 0, 1, 0
- 每个元素选择符,伪元素,加 0, 0, 0, 1
- 连接符和通用选择符不增加特指度。
例如:
h1 {
color: red;
} /* specificity = 0,0,0,1 */
p em {
color: purple;
} /* specificity = 0,0,0,2 */
.grape {
color: purple;
} /* specificity = 0,0,1,0 */
*.bright {
color: yellow;
} /* specificity = 0,0,1,0 */
p.bright em.dark {
color: maroon;
} /* specificity = 0,0,2,2 */
#id216 {
color: blue;
} /* specificity = 0,1,0,0 */
div#sidebar *[href] {
color: silver;
} /* specificity = 0,1,1,1 */
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 声明和特指度
h1 {
color: silver;
background: black;
}
2
3
4
浏览器执行时会将它打散为单独的规则:
h1 {
color: silver;
}
h1 {
background: black;
}
2
3
4
5
6
多个选择符作用于同一个元素上时,不同属性均会生效,相同的属性依据特指度高者生效。
# 通用选择符的特指度
通用选择符不增加特指度,特指度为 0,0,0,0 。但它与没有特指度是不同的。
div p {} /* 0,0,0,2 */
body * strong {} /* 0,0,0,2 */
2
3
# ID 和属性选择符的特指度
ID选择符合属性选择符使用id时是有区别的
#meadow {
color: green;
} /* 0,1,0,0 */
*[id='meadow'] {
color: red;
} /* 0,0,1,0 */
html > body table tr[id='totals'] td ul > li {
color: maroon;
} /* 0,0,1,7 */
li#answer {
color: navy;
} /* 0,1,0,1 (胜出) */
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 行内样式的特指度
行内样式声明的特指度比其他声明都高。特指度为 1, 0, 0, 0
# 重要声明 !important
有时某个声明非常重要,超过其他所有声明,称为重要声明(important declarations)。
在声明末尾的分号之前加上 !important
即可:
p.dark {
color: #333 !important; /* 选中元素的的此属性超过其他一切声明 */
background: white;
}
2
3
4
# 继承
继承指设定的样式不仅作用在选中元素上,还作用到其所有后代身上。
很多属性不会继承,比如多数盒模型的属性,包括 margin padding background border
等。
继承的值没有特指度,连 0 都没有。所以 0 特指度的 通用选择符会战胜 没有特指度的继承样式。
# 层叠
如果特指度完全相同,则后声明的覆盖先声明的样式。
如果一个样式表中,样式和 头部的 @import
的样式冲突,则当前样式表中的生效,引入的样式都算在引入的位置,当前样式表中的样式位置算在它的后面声明。
正因为前后位置有影响,所以通常才推荐按照一定的顺序编写链接的样式。
a:link {
color: blue;
}
a:visited {
color: purple;
}
a:focus {
color: green;
}
a:hover {
color: red;
}
a:active {
color: orange;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
因为以上选择符的特指度相等,都是 0, 0, 1, 0。所以最后匹配的会生效。
试想,点击(active)的时候,如果 a:active
没有写在最后,则会被它后面的样式覆盖。
如果按照以下顺序设置链接样式:
a:active {
color: orange;
}
a:focus {
color: green;
}
a:hover {
color: red;
}
a:link {
color: blue;
}
a:visited {
color: purple;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a:active
,a:focus
,a:hover
永远都不会生效,因为 a:link
和 a:visited
在它们后面,一个链接要么已访问,要么是未访问,a:link
和 a:visited
总有一个会覆盖前面的样式。
当然,以上的所有冲突只会发生在设置相同的属性的时候,设置不同的属性则不会被影响。还有就是 :link
和 :visited
样式的顺序并不重要,因为未访问和已访问是不会同时被匹配到的。
把伪类串在一起可以消除这一系列的问题:
a:link {
color: blue;
}
a:visited {
color: purple;
}
a:link:hover {
color: red;
}
a:visited:hover {
color: gray;
}
2
3
4
5
6
7
8
9
10
11
12
以上样式任意调换顺序都不会有影响。
但是,加上 :active
状态后,顺序又变得重要了:
a:link {
color: blue;
}
a:visited {
color: purple;
}
a:link:hover {
color: red;
}
a:visited:hover {
color: gray;
}
a:link:active {
color: orange;
}
a:visited:active {
color: silver;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
如果把上述的 :active
移到 :hover
之前,那么 :active
将会被忽略。
解决办法就是增加串联的伪类数量
a:link {
color: blue;
}
a:visited {
color: purple;
}
a:link:hover:active {
color: orange;
} /* 特指度增加,不会被 hover 取代 */
a:visited:hover:active {
color: silver;
} /* 特指度增加,不会被 hover 取代 */
a:link:hover {
color: red;
}
a:visited:hover {
color: gray;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20