CSS 结构和层叠总结

CSS 特殊性(CSS Specificity)

首先看下面这个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- HTML -->
<body>
<h1>this is heading 1.</h1>
<h2 class="grape">this is heading 2.</h2>
<table>
<tr id="totals">
<td>
<ul>
<li id="answer">this is contents of the list.</li>
</ul>
</td>
</tr>
<!-- /totals -->
</table>
</body>
1
2
3
4
5
6
7
8
9
/* CSS */
h1 {color: red;}
body h1 { color: green;}

h2.grape {color: purple;}
h2 {color: silver;}

html > body table tr[id="totals"] td ul > li {color: maroon;}
li#answer {color: navy;}

以上CSS属性声明那个规则更强?

答案如下:

  • body h1 > h1
  • h2.grape > h2
  • li#answer > html > body table tr[id="totals"] td ul > li

点击查看Demo

CSS 特殊性值

选择器的特殊性值表述为4个部分,如:0, 0, 0, 0

选择器的具体特殊性值如下:

  • 选择器中的ID属性值: 0, 1, 0, 0; 例:#id
  • 选择器中类属性值、属性选择、伪类: 0, 1, 0, 0; 例:.className*[attribute]:hover
  • 选择器中的元素、伪元素:0, 0, 0, 1; 例:divdiv::beforediv::after
  • 结合符、通配选择器:0, 0, 0, 0; 例:*>
  • HTML元素中的内联样式特殊性都是:1,0,0,0; 例:<div style="color: black; font-size: 20px">test</div>

例子如下:

1
2
3
4
5
6
7
8
<!-- HTML -->
<body>
<h1>Section Heading 1 Part.</h1>
<p class="grape">This is a grape paragraph.</p>
<p class="bright">This is a bright paragraph and <em class="dark">dark</em>.</p>
<p id="element">this is a paragraph.</p>
<div id="sidebar">This is sidebar div and <a href="#x">alink text.</a></div>
</body>
1
2
3
4
5
6
7
8
/* CSS */
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 */
#element {color: blue;} /* specificity = 0, 1, 0, 0 */
div#sidebar *[href="#x"] {color: silver;} /* specificity = 0, 1, 1, 1 */

需要注意的地方:

0, 0, 1, 0 要大于0, 0, 0, 13
特殊性是从左向右排序的,特殊性值1, 0, 0, 0大于以0开头的所有特殊性值,不论后面的数字是什么

CSS 声明和特殊性

1、确定一个选择器的特殊性,这个值将会授予其所有相关声明,如下所示:

1
2
<!-- HTML -->
<h1>Section Heading 1 Part.</h1>
1
2
3
/* CSS */
h1 {color: silver; background: black;}
/* h1标签的color和background属性的特殊性都为:0, 0, 0, 1 */

2、多条规则会被用户代理“解组”为单独的规则,如下所示:

1
2
<!-- HTML -->
<h1>Section Heading 1 Part.</h1>
1
2
3
4
5
6
7
/* CSS */
h1 {color: silver; background: black;}
/* 解组后 */
h1 {color: silver;}
h1 {background: black;}

/* 这两个规则的特殊性都是:0, 0, 0, 1,各声明得到的特殊性值也就是:0, 0, 0, 1 */

3、分组选择器会被用户代理“解组”为单独的规则,如下所示:

1
2
3
<!-- HTML -->
<h1>Section Heading 1 Part.</h1>
<h2 class="section">Section Heading 1 Part.</h2>
1
2
3
4
5
6
7
8
9
/* CSS */
h1, h2.section {color: silver; background: black;}

/* 解组后 */
h1 {color: silver;} /* 0, 0, 0, 1 */
h1 {background: black;} /* 0, 0, 0, 1 */

h2.section {color: silver;} /* 0, 0, 1, 1 */
h2.section {background: black;} /* 0, 0, 1, 1 */

4、“解组”完后,单独选择器的单独规则开始根据计算出来的最高特殊性值来显示元素

通配选择器特殊性

1、通配选择器*的特殊性值为:0, 0, 0, 0,但需要注意的是通配选择器不等于没有特殊性(设置了要比没有设置强)

例子如下:

1
2
3
4
5
6
7
8
9
10
<!-- HTML -->
<html>
<body>
<div>
<p>This is a paragraph.</p>
</div>
<p>This is a paragraph.</p>
<p>This is a paragraph.</p>
</body>
</html>
1
2
3
4
/* CSS */
div p {color: black;} /* 0, 0, 0, 2 */
* {color: gray;} /* 0, 0, 0, 0 */
/* 根据特殊性的值来计算div下包含的段落都是黑色,其他元素都是灰色 */

2、如果一个选择器中包含通配选择器和其他选择器,选择器的特殊性不会因为通配选择器的出现发生改变,如下所示:

1
2
3
4
5
6
<!-- HTML -->
<body>
<div>
<p>This is a paragrah<strong> Strong text</strong></p>
</div>
</body>
1
2
3
4
/* CSS */
div p {color: black;} /* 0, 0, 0, 2 */
body * strong {color: yellow;} /* 0, 0, 0, 2 */
/* 上面两个选择器的特殊性完全相等 */

ID和属性选择器的特殊性

ID选择器和指定ID属性的属性选择器在特殊性上有所不同,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- HTML -->
<html>
<head></head>
<body>
<table>
<tr id="totals">
<td>
<ul>
<li id="answer">Answer Content</li>
</ul>
</td>
</tr>
</table>
</body>
</html>
1
2
3
/* CSS */
html > body table tr[id="totals"] td ul > li {color: maroon;} /* 0, 0, 1, 7 */
li#answer {color: navy;} /* 0, 1, 0, 1 (Winner)*/

内联样式特殊性

通常,特殊性的第一个0是为内联样式声明保留,它要比所有其他声明的特殊性都要高
内联样式声明的特殊性为:1, 0, 0, 0

例子如下:

1
2
<!-- HTML -->
<h1 style="color: green;" id="header">The meadow party</h1> /* 1, 0, 0, 0 */
1
2
3
4
/* CSS */
h1#header {color: red;} /* 0, 1, 0, 1 */

/* 因为内联样式特殊性要比其他声明的特殊性都高, 所以这里h1元素的文字内容颜色是绿色 */

CSS 重要性(CSS !Important)

  • 重要性标识:在样式的声明分号前插入:!important;
  • 标志为!important;的声明规则,没有特殊性的特殊性值,优先级是最高的

例子如下:

1
2
<!-- HTML -->
<h1 class="title">NightWing</h1>
1
2
3
4
5
6
7
8
9
10
11
12
/* CSS */
h1 {font-style: italic; color: gray !important;}
.title {color: black; background: silver;}
* {background: black !important;}

/* 因为添加了!important;的样式是优先级最高的,所以这里h1元素的最终样式应该为:
h1.title {
font-style: italic;
color: gray !important;
background: black !important;
}
*/

CSS 继承(CSS Inheritance)

继承的值没有特殊性,甚至连0都没有;也就是说,0特殊性要比无特殊性更强(特殊性为0高于继承)

1、0特殊性比无特殊性要强,例子如下:

1
2
3
<!-- HTML -->
<h1 id="page-title">Meerkat <em>Central</em></h1>
<p>Welcome to the best place on the web for meerkat information!</p>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* CSS */
* {color: gray;} /* 0, 0, 0, 0*/
h1#page-title {color: black;} /* 0, 1, 0, 1 */

/*
因为这里em的color属性没有声明,先从h1元素继承,但又给通配选择器*声明了color属性
0 > 无特殊性
所以最终呈现出来的样式为:
h1#page-title {
color: black;
}
em {
color: gray;
font-style: italic;
}
p {
color: gray;
}
*/

2、不加区别地使用通配选择器(*)可能存在一些问题,需谨慎使用通配选择器(*

通配选择器(*)能匹配任何元素,又是0特殊性,优先于继承值,所以有一种短路继承的效果
为了避免这个问题,避免不加区别地使用通配选择器(*),从根本上解决这个问题

3、子元素是<a>标签,<a>标签会使用浏览器用户代理样式表中的伪类样式(a:link),需要单独为<a>定义样式规则

例子如下:

1
2
<!-- HTML -->
<section id="toolbar">This is toolbar part <a href="#x">this is alink elements.</a>
1
2
3
/* CSS */
#toolbar {color: white; background: black;}
#toolbar a:link {color: white;}

CSS可继承属性与不可继承属性

思考一个问题:CSS中所有的属性都可以继承吗?

答案显然是否定的,在CSS中有些属性可以继承,有些不行。
那么,那些CSS属性可以继承,那些CSS属性不能继承?

简单列举一部分例子如下:

CSS 可继承属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/* CSS 字体系列属性 */
font: /* 组合字体 */
font-family: /* 规定元素的字体系列 */
font-weight: /* 设置字体的粗细 */
font-size: /* 设置字体的尺寸 */
font-style: /* 定义字体的风格 */
font-variant: /* 偏大或偏小的字体 */

/* CSS 文本系列属性 */
text-indent: /* 文本缩进 */
text-align: /* 文本水平对刘 */
line-height: /* 行高 */
word-spacing: /* 增加或减少单词间的空白 */
letter-spacing: /* 增加或减少字符间的空白 */
text-transform: /* 控制文本大小写 */
direction: /* 规定文本的书写方向 */
color: /* 文本颜色 */

/* CSS 元素可见性 */
visibility:

/* CSS 表格布局属性 */
caption-side: /* 定位表格标题位置 */
border-collapse: /* 合并表格边框 */
border-spacing: /* 设置相邻单元格的边框间的距离 */
empty-cells: /* 单元格的边框的出现与消失 */
table-layout: /* 表格的宽度由什么决定 */<automatic.fixed.inherit>

/* CSS 列表布局属性 */
list-style-type: /* 文字前面的小点点样式 */
list-style-position: /* 小点点位置 */
list-style: /* 以上的属性可通过这属性集合 */

/* CSS 引用 */
quotes: /* 设置嵌套引用的引号类型 */

/* CSS 光标属性 */
cursor: /* 箭头可以变成需要的形状 */

/* CSS 页面样式属性 */
pagepage-break-insidewindowsorphans

/* CSS 声音样式属性 */
speakspeak-punctuationspeak-numeralspeak-headerspeech-ratevolumevoice-familypitchpitch-rangestressrichness、、azimuthelevation

所有元素可以继承的属性

元素可见性:visibility
光标属性:cursor

内联元素可以继承的属性

字体系列属性
text-indenttext-align之外的文本系列属性

块级元素可以继承的属性

text-indenttext-align

CSS 不可继承属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
displey

/* CSS 文本属性 */
vertical-align: /* 垂直文本对齐 */
text-decoration: /* 规定添加到文本的装饰 */
text-shadow: /* 文本阴影效果 */
white-space: /* 空白符的处理 */

/* CSS 盒子模型属性 */
widthheightmarginmargin-topmargin-rightmargin-bottommargin-leftborderborder-styleborder-top-styleborder-right-styleborder-bottom-styleborder-left-styleborder-widthborder-top-widthborder-right-rightborder-bottom-widthborder-left-widthborder-colorborder-top-colorborder-right-colorborder-bottom-colorborder-left-colorborder-topborder-rightborder-bottomborder-leftpaddingpadding-toppadding-rightpadding-bottompadding-left

/* CSS 背景属性 */
backgroundbackground-colorbackground-imagebackground-repeatbackground-positionbackground-attachment

/* CSS 定位属性 */
floatclearpositiontoprightbottomleftmin-widthmin-heightmax-widthmax-heightoverflowclipz-index

/* CSS 生成内容属性 */
contentcounter-resetcounter-increment

/* CSS 轮廓样式属性 */
outline-styleoutline-widthoutline-coloroutline

/* CSS 页面样式属性 */
sizepage-break-beforepage-break-after

/* CSS 声音样式属性 */
pause-beforepause-afterpausecue-beforecue-aftercueplay-during

CSS 层叠(CSS Cascading)

层叠规则

以下样式中,那条样式的声明会起作用?

1
2
<!-- HTML -->
<h1>This is Heading 1.</h1>
1
2
3
/* CSS */
h1 {color: red;}
h1 {color: blue;}
  • !important; 重要性标识优先
  • 按来源对应用到给定元素的所有声明排序有3种来源:创作人员 > 读者 > 用户代理(user agent)
  • 按特殊性对应用到给定元素的所有声明排序,高特殊性 > 低特殊性
  • 按出现顺序对应用到给定元素的所有声明排序,在样式表或文档中越后出现,权重越大

如果两个规则的权重、来源、特殊性完全相同,则样式表中后出现的一个规则会被使用


按权重和来源排序

1、!important; 重要性标识优先

例子如下:

1
2
<!-- HTML -->
<p style="color: black;">This is a <em>paragraph</em>.</p>
1
2
3
4
5
6
7
/* CSS */
p {color: gray !important;}

/*
根据!important重要标识优先的规则
最终呈现出来的样式应该是灰色,并且后面的em元素也会继承灰色
*/

参考内容