HTML+CSS宝典 CSS基础 层叠
css 叫做层叠样式表 ( 英文全称:Cascading Style Sheets ),
层叠 css 里面不仅是一个重要的知识,也是一个非常基础的知识,了解层叠知识过后,以后面对某些场景的时候才知道该怎么去处理。
要理解层叠,先要理解一个概念叫声明冲突,
声明冲突的意思就是同一个样式,多次应用到了同一个元素,就叫做声明冲突。
一、声明冲突
看这个例子,给10个a元素设置样式
1. color: red a元素的颜色设置成红色
2. text-decoration: none 去掉下滑线
好像没有什么声明冲突!
01 | <!DOCTYPE html> |
02 | < html > |
03 | < head > |
04 | < meta charset = "UTF-8" > |
05 | < style > |
06 | a{ |
07 | color: red; |
08 | text-decoration: none; |
09 | } |
10 | </ style > |
11 | < title >声明冲突</ title > |
12 | </ head > |
13 | < body > |
14 | < a href = "" >Lorem.</ a > |
15 | < a href = "" >Pariatur.</ a > |
16 | < a href = "" >Inventore.</ a > |
17 | < a href = "" >Quaerat.</ a > |
18 | < a href = "" >Velit!</ a > |
19 | < a href = "" >Porro.</ a > |
20 | < a href = "" >Et!</ a > |
21 | < a href = "" >Non.</ a > |
22 | < a href = "" >Necessitatibus!</ a > |
23 | < a href = "" >Quasi.</ a > |
24 | </ body > |
25 | </ html > |
右键检查(F12)看一下,随便找一个a元素,点击选中a元素
看右边的样式表里面有两个样式应用到了a元素
1. 一个是我们自己写的样式
2. 一个是浏览器默认的样式(user agent stylesheet)也设置了颜色
a 元素具备了两个样式,两个样式怎么办呢?
有的时候一个元素可能有多个样式影响到它,而这些样式里面有一些相同的属性,这些相同的属性就产生了冲突,这就是声明冲突。
这个例子里,a元素有两个声明冲突,一个是 color 属性、一个是 text-decoration 属性,这是关于声明冲突的概念。
声明冲突是不是只会发生在 我们写的样式 跟浏览器默认的样式表之间,
其它的情况就不会发生声明冲突了,因为我们写的代码应该尽量的避免声明冲突,实际上不是这样子的,
有时候我们的代码就是要 声明冲突 为什么呢?
看一个例子,
比如下面的 a 元素全部应用了一些统一的样式
1. 文字颜色是红色 color: red
没有下划线 text-decoration: none
斜体 font-style: italic
2. 但其中一个 a 元素比较特殊,专门给这个特殊的 a 元素加一个类样式 .selected(表示被激活的),
文字颜色为白色 color: #fff、背景为红色 background-color: red ,表示这个a元素被选中
01 | <!DOCTYPE html> |
02 | < html > |
03 | < head > |
04 | < meta charset = "UTF-8" > |
05 | < style > |
06 | a{ |
07 | color: red; |
08 | text-decoration: none; |
09 | font-style:italic; |
10 | } |
11 | .selected{ |
12 | color:#fff; |
13 | background-color:red; |
14 | } |
15 | </ style > |
16 | < title >声明冲突</ title > |
17 | </ head > |
18 | < body > |
19 | < a href = "" >Lorem.</ a > |
20 | < a href = "" >Pariatur.</ a > |
21 | < a href = "" >Inventore.</ a > |
22 | < a href = "" class = "selected" >Quaerat.</ a > |
23 | < a href = "" >Velit!</ a > |
24 | < a href = "" >Porro.</ a > |
25 | < a href = "" >Et!</ a > |
26 | < a href = "" >Non.</ a > |
27 | < a href = "" >Necessitatibus!</ a > |
28 | < a href = "" >Quasi.</ a > |
29 | </ body > |
30 | </ html > |
3. 我们希望有些 统一的样式 是要保留的,有些是要被 特殊的样式 覆掉盖的
4. 这个特殊的a元素( .selected )大部分样式和其它a元素是一样的,
斜体属性保留了,去掉下划线样式保留了,我们只是改了字体颜色 和 背景颜色
开发中我们经常遇到这样的场景,
上面的代码还是一个简单的场景,实际上很多时候在更复杂的场景,我们会人为的去制造冲突,
当这些重复发生的时候,我们要解决冲突,这个解决冲突的过程就叫做层叠。
层叠的意思:解决声明冲突的过程,这个层叠是浏览器自动处理的。
我们要学习浏览器是怎么处理声明冲突的,我们了解了浏览器的处理过程,我们才能在人为的制造冲突的时候很好的控制,才能把我们希望覆盖的样式给覆盖掉。
二、权重计算
层叠在有些地方叫权重计算( 是一样的意思但叫法不一样 )
权重计算会经过三步过程
第一步,比较重要性
第二步,比较特殊性
第三步,比较源次序
上面这三个步骤非常简单,经过这三个步骤的比较,比较完成之后一定能够有一个最终的样式胜出
1、第一步,比较重要性
重要性从高到底就看三步
第一步,
作者样式表中的 !important 样式( 作者样式表的意思是,开发者写的样式 )
color: red !important 加了 !important 后的样式,重要性是最高的,
但是不建议加 !important,因为它的重要程度太高了,今后要想覆盖覆盖不掉,想覆盖也要加 !important
第二步,
作者样式表中的普通样式(就是没有加 !important 的样式)
第三步,
浏览器默认样式表( 浏览器代理 )中的样式
上面这三步从高到底排序,高的就一定把底的淘汰掉
01 | <!DOCTYPE html> |
02 | <html> |
03 | <head> |
04 | <meta charset= "UTF-8" > |
05 | <style> |
06 | a{ |
07 | color : red !important ; /* !important 表示这是一个重要样式 */ |
08 | text-decoration : none ; /* 作者样式表中的普通样式 */ |
09 | font-style : italic ; /* 作者样式表中的普通样式 */ |
10 | } |
11 | .selected{ |
12 | color : #fff ; /* 作者样式表中的普通样式 */ |
13 | background-color : red ; /* 作者样式表中的普通样式 */ |
14 | } |
15 | </style> |
16 | <title>声明冲突</title> |
17 | </head> |
18 | <body> |
19 | <a href= "" >Lorem.</a> |
20 | <a href= "" >Pariatur.</a> |
21 | <a href= "" >Inventore.</a> |
22 | <a href= "" class= "selected" >Quaerat.</a> |
23 | <a href= "" >Velit!</a> |
24 | <a href= "" >Porro.</a> |
25 | <a href= "" >Et!</a> |
26 | <a href= "" >Non.</a> |
27 | <a href= "" >Necessitatibus!</a> |
28 | <a href= "" >Quasi.</a> |
29 | </body> |
30 | </html> |
color 属性发生了冲突,color 属性出现在三个地方,
1. 一个作者样式表(普通样式)
2. 一个是作者样式表的重要样式 !important ( 胜出 )
3. 一个是浏览器默认样式表中的样式
一定是作者样式表的重要样式胜出
作者样式表的重要样式胜出,冲突已经解决了,第二步比较特殊性、第三步比较源次序,就不在进行了
2、第二步,比较特殊性
第二步比较特殊性,什么时候发生呢?
发生的时间在第一步比较重要性完成之后冲突还没有解决,还剩下几个有冲突的属性没有解决,它们的重要性是一样,这个时候进入第二步比较特殊性。
把 css 代码中重要样式 !important 去掉
01 | <!DOCTYPE html> |
02 | <html> |
03 | <head> |
04 | <meta charset= "UTF-8" > |
05 | <style> |
06 | a{ |
07 | color : red ; |
08 | text-decoration : none ; |
09 | font-style : italic ; |
10 | } |
11 | .selected{ |
12 | color : #fff ; |
13 | background-color : red ; |
14 | } |
15 | </style> |
16 | <title>比较特殊性</title> |
17 | </head> |
18 | <body> |
19 | <a href= "" >Lorem.</a> |
20 | <a href= "" >Pariatur.</a> |
21 | <a href= "" >Inventore.</a> |
22 | <a href= "" class= "selected" >Quaerat.</a> |
23 | <a href= "" >Velit!</a> |
24 | <a href= "" >Porro.</a> |
25 | <a href= "" >Et!</a> |
26 | <a href= "" >Non.</a> |
27 | <a href= "" >Necessitatibus!</a> |
28 | <a href= "" >Quasi.</a> |
29 | </body> |
30 | </html> |
color 属性出现了三次,
1. 两个是作者样式表的普通样式,这两个的重要性是一样的,
2. 所以只能淘汰浏览器的默认样式,
3. 因此第一步比较完了之后还有冲突,进入第二步的比较比较特殊性
比较特殊性有一个总体规则,总体规则就是看选择器
总体规则,
选择器选中的范围越窄,越特殊。
比如id选择器只能选中一个,他选择的范围太窄所以很特殊,
有些选择器选择的范围很广,比如通配符选择器、元素选择器,这些选择器选择的范围很广,那么它们就不太特殊,
所以按照总体规则就已经可以解决很多问题了。
a{} 和 .selected{} 都是作者样式表,重要性是一样的,进入第二步比较特殊性,谁特殊?
1. a{} 是元素选择器选择范围很广
2. .selected{} 是类选择器范围要窄一些,所以 .selected{} 更特殊最终胜出
很多时候比较特殊性这块,记住总体规则就已经能搞定了,
但是哪些选择器更窄,哪些选择器更特殊,这里要理解透彻,浏览器具体是怎么比较特性的,浏览器怎么做的的呢?
浏览器要确定一个四位数(千位、百位、十位、个位),怎么来计算这4位数呢?
具体规则,
通过选择器,计算出一个4位数(千位、百位、十位、个位),比较这四位数( 这四位数哪个大哪个就越特殊 )。
千位:
如果内联样式,记作1,否则记0
如果样式是写在元素里面的内联样式 style="color: chocolate"
<a href="" class="selected" style="color: chocolate">Quaerat.</a>
在比较四位数的时候,这个四位数的千位是1,
其它样式的千位是0,因为其它的都不是内联样式(千位都是0)
01 | <!DOCTYPE html> |
02 | < html > |
03 | < head > |
04 | < meta charset = "UTF-8" > |
05 | < style > |
06 | a{ |
07 | color: red; |
08 | text-decoration: none; |
09 | font-style:italic; |
10 | } |
11 | .selected{ |
12 | color:#fff; |
13 | background-color:red; |
14 | } |
15 | </ style > |
16 | < title >比较千位</ title > |
17 | </ head > |
18 | < body > |
19 | < a href = "" >Lorem.</ a > |
20 | < a href = "" >Pariatur.</ a > |
21 | < a href = "" >Inventore.</ a > |
22 | < a href = "" class = "selected" style = "color:chocolate" >Quaerat.</ a > |
23 | < a href = "" >Velit!</ a > |
24 | < a href = "" >Porro.</ a > |
25 | < a href = "" >Et!</ a > |
26 | < a href = "" >Non.</ a > |
27 | < a href = "" >Necessitatibus!</ a > |
28 | < a href = "" >Quasi.</ a > |
29 | </ body > |
30 | </ html > |
百位:
等于选择器中所有 id 选择器的数量,
意思是样式表里面有没有 id 选择器,比如加一个 id 选择器 #mylink,id 选择器只能选择一个元素,所以 id 选中器很特殊
下面 a 元素有,
元素选择器、类选择器、id选择器,他们都有color属性的冲突,color属性的值用什么颜色?
01 | <!DOCTYPE html> |
02 | < html > |
03 | < head > |
04 | < meta charset = "UTF-8" > |
05 | < style > |
06 | a{ |
07 | color: red; |
08 | text-decoration: none; |
09 | font-style:italic; |
10 | } |
11 | #mylink{ |
12 | color:yellow; |
13 | } |
14 | .selected{ |
15 | color:#fff; |
16 | background-color:red; |
17 | } |
18 | </ style > |
19 | < title >比较百位</ title > |
20 | </ head > |
21 | < body > |
22 |
23 | < a href = "" class = "selected" id = "mylink" >Quaerat.</ a > |
24 |
25 | </ body > |
26 | </ html > |
1. 都不是内联样式,千位都是0,比较百位,
2. 百位等于是id选择器的数量,#mylink id选择器的数量百位是1,其它选择器的百位是0
a 0 0 ? ?
#mylink 0 1 ? ?
.selected 0 0 ? ?
所以得到的结果是 color: yellow 黄颜色胜出
如果百位都一样,那么比较十位
十位:
等于选择器中所有 类选择器、属性选择器、伪类选择器 的数量。
类选择器、属性选择器、伪类选择器,这三种选择器他们的特殊性都差不多,这些选择器的数量加起来就是十位的数量
01 | <!DOCTYPE html> |
02 | <html> |
03 | <head> |
04 | <meta charset= "UTF-8" > |
05 | <style> |
06 | /* 000? */ |
07 | a{ |
08 | color : red ; |
09 | text-decoration : none ; |
10 | font-style : italic ; |
11 | } |
12 | /* 001? 这里千位是0,百位是0,十位类选择器是1,所以胜出 */ |
13 | .selected{ |
14 | color : #fff ; |
15 | background-color : red ; |
16 | } |
17 | </style> |
18 | <title>比较十位</title> |
19 | </head> |
20 | <body> |
21 |
22 | <a href= "" class= "selected" >Quaerat.</a> |
23 |
24 | </body> |
25 | </html> |
a 000?
.selected 001? 千位没有内联是0,百位没有id是0,十位类选择器有一个是1,十位比上面的高所以胜出
个位:
等于选择器中所有 元素选择器、伪元素选择器 的数量
01 | <!DOCTYPE html> |
02 | <html> |
03 | <head> |
04 | <meta charset= "UTF-8" > |
05 | <style> |
06 | /* 不是内联、不是id、不是类选择器,只有一个元素选择器 0001 */ |
07 | a{ |
08 | color : red ; |
09 | text-decoration : none ; |
10 | font-style : italic ; |
11 | } |
12 | /* 不是内联、不是id、不是类选择器,有两个元素选择器 0002,所以它胜出 */ |
13 | body a{ |
14 | color :yellow; |
15 | background-color : red ; |
16 | } |
17 | </style> |
18 | <title>比较个位</title> |
19 | </head> |
20 | <body> |
21 |
22 | <a href= "" >Quaerat.</a> |
23 |
24 | </body> |
25 | </html> |
body a 不是内联千位是0、没有id百位是0、没有类选择器十位是0,元素选择器有两个为 2 ,0002 这个胜出
a 不是内联千位是0、没有id百位是0、没有类选择器十位是0,元素选择器只有一个为1,0001
比较特殊性的练习,
下面样式的重要性是一样的,都是作者样式表,
但是特殊性是不一样的,比较更特殊性谁最高,最后 a 元素是什么颜色?
01 | <!DOCTYPE html> |
02 | <html> |
03 | <head> |
04 | <meta charset= "UTF-8" > |
05 | <style> |
06 | /* 0001 */ |
07 | a{ |
08 | color : red ; |
09 | } |
10 | /* 0003 */ |
11 | div ul a{ |
12 | color : green ; |
13 | } |
14 | /* 0201 */ |
15 | #mydiv #myul a{ |
16 | color : #ccc ; |
17 | } |
18 | /* 0211 */ |
19 | #mydiv #myul a:link{ |
20 | color :chocolate; |
21 | } |
22 | /* 0210 */ |
23 | #mydiv #myul .mylink{ |
24 | color : #008c8c ; |
25 | } |
26 | </style> |
27 | <title>练习—比较特殊性</title> |
28 | </head> |
29 | <body> |
30 | <div id= "mydiv" > |
31 | <ul id= "myul" > |
32 | <li id= "myli" > |
33 | <a href= "http://163.com" class= "mylink" > |
34 | 举个例子 |
35 | </a> |
36 | </li> |
37 | </ul> |
38 | </div> |
39 | <!-- |
40 | div#mydiv |
41 | ul#myul |
42 | li* 1 #myli |
43 | --> |
44 | </body> |
45 | </html> |
#mydiv #myul a:link
有2个百位id选择器,1个十位的伪类选择器,1个的个位元素选择器
这里有一个细节,
这四位数不是逢十进一,专门有人测过是逢 256 进一,所以比较的时候不用考虑进位的问题。
看一个例子
.tbh-nav h2 是淘宝中的css代码, .tbh-nav .tb-bg h2 可以多写了一个类选择器 .tb-bg,特殊性高了有冲突的样式就被覆盖掉了
01 | .tbh-nav h 2 { |
02 | float : left ; |
03 | width : 190px ; |
04 | text-align : center ; |
05 | font-size : 16px ; |
06 | background : #ff5000 ; |
07 | } |
08 | .tbh-nav .tb-bg h 2 { |
09 | background : #008c8c ; |
10 | } |
不要去改别人的代码,我们通常是用冲突的方式,利用层叠的规则覆盖之前的代码,
比如临近春节重大节日的时候,网站的皮肤都会改版,这个时候往往加一个 link 样式表,把之前的一些样式、颜色覆盖掉,
过完年把这个 link 文件去掉就可以了。
3、第三步,比较源次序
特殊性一样的时候,冲突还是解决不了,这个时候就比较源次序
源次序的意思是代码靠后的胜出 ,到了这一步一定只能剩一个样式了,因为书写代码总有一个前后顺序
01 | <!DOCTYPE html> |
02 | <html> |
03 | <head> |
04 | <meta charset= "UTF-8" > |
05 | <style> |
06 | /* 0001 */ |
07 | a{ |
08 | color : red ; |
09 | } |
10 | /* 0003 */ |
11 | div ul a{ |
12 | color : green ; |
13 | } |
14 | /* 0201 */ |
15 | #mydiv #myul a{ |
16 | color : #ccc ; |
17 | } |
18 | /* 0210 */ |
19 | #mydiv #myul :link{ |
20 | color :chocolate; |
21 | } |
22 | /* 0210 书写靠后的马尔斯绿色胜出 */ |
23 | #mydiv #myul .mylink{ |
24 | color : #008c8c ; |
25 | } |
26 | </style> |
27 | <title>比较源次序</title> |
28 | </head> |
29 | <body> |
30 |
31 | <div id= "mydiv" > |
32 | <ul id= "myul" > |
33 | <li id= "myli" > |
34 | <a href= "http://163.com" class= "mylink" > |
35 | 举个例子 |
36 | </a> |
37 | </li> |
38 | </ul> |
39 | </div> |
40 |
41 | </body> |
42 | </html> |
三、层叠的应用
第一个应用,重置样式表
作者样式的重要性要高于浏览器的默认样式的,
网上有这样一些常见的重置样式表 normalize.css、reset.css、meyer.css
袁老师喜欢用这个 meyer.css
02 | v2.0 | 20110126 |
03 | License: none (public domain) |
04 | */ |
05 |
06 | html, body, div, span, applet, object, iframe, |
07 | h 1 , h 2 , h 3 , h 4 , h 5 , h 6 , p, blockquote, pre , |
08 | a, abbr, acronym, address, big, cite, code , |
09 | del, dfn, em, img, ins, kbd, q, s, samp, |
10 | small , strike, strong, sub , sup, tt, var, |
11 | b, u, i, center , |
12 | dl, dt, dd, ol, ul, li, |
13 | fieldset, form, label, legend, |
14 | table, caption , tbody, tfoot, thead, tr, th, td, |
15 | article, aside, canvas, details, embed , |
16 | figure, figcaption, footer, header, hgroup, |
17 | menu, nav, output, ruby, section, summary, |
18 | time, mark, audio, video { |
19 | margin : 0 ; |
20 | padding : 0 ; |
21 | border : 0 ; |
22 | font-size : 100% ; |
23 | font : inherit; |
24 | vertical-align : baseline ; |
25 | } |
26 | /* HTML5 display-role reset for older browsers */ |
27 | article, aside, details, figcaption, figure, |
28 | footer, header, hgroup, menu, nav, section { |
29 | display : block ; |
30 | } |
31 | body { |
32 | line-height : 1 ; |
33 | } |
34 | ol, ul { |
35 | list-style : none ; |
36 | } |
37 | blockquote, q { |
38 | quotes : none ; |
39 | } |
40 | blockquote:before, blockquote:after, |
41 | q:before, q:after { |
42 | content : '' ; |
43 | content : none ; |
44 | } |
45 | table { |
46 | border-collapse : collapse ; |
47 | border-spacing : 0 ; |
48 | } |
第二个应用,爱恨法则
a 元素在写伪类的时候的顺序 link -> visited -> hover -> active ,为什么要这个顺序呢?跟源次序有关
01 | <!DOCTYPE html> |
02 | <html> |
03 | <head> |
04 | <meta charset= "UTF-8" > |
05 | <style> |
06 | /* 没有访问过,颜色是绿色 */ |
07 | a:link{ |
08 | color : green ; |
09 | } |
10 | /* 访问过了,颜色是红色 */ |
11 | a:visited{ |
12 | color : red ; |
13 | } |
14 | /* 鼠标移上去的时候,颜色是巧克力色 */ |
15 | a:hover{ |
16 | color : chocolate; |
17 | } |
18 | /* 鼠标按下去的时候,颜色是黑色 */ |
19 | a:active{ |
20 | color : #000 ; |
21 | } |
22 | </style> |
23 | <title>爱恨法则</title> |
24 | </head> |
25 | <body> |
26 |
27 | <a href= "http://163.com" >网易</a> |
28 |
29 | </body> |
30 | </html> |