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