HTML+CSS宝典 CSS基础 属性值的计算过程
属性值的计算的过程这块知识网上搜不到,在很多教程里面都没有出现,但是这块知识非常重要,他能让我们从更高的角度来看待,一个网页是如何渲染出来的。
属性值的计算的过程,过程非常非常的复杂,其实讲的就是页面渲染的过程,浏览器是怎么把页面渲染出来的,这个过程是很复杂的里面有很多很多的细节。
但是对应我们来说,了解它精简出来的最核心的点就可以了,了解这些核心点之后,对我们就非常非常有帮助了,我们再看页面的渲染,思路就会非常的清晰。
首先说的一个点,
浏览器要渲染一个页面,是一个元素一个元素的依次渲染的,顺序按照页面文档的树形目录结构进行。
一、树形目录结构
网页页面是树形的目录,目录的根节点是<HTML>元素,渲染的时候是从上到下,从父元素开始一个一个的渲染
1. 先渲染 HTML 元素,
2. 渲染 html 元素完成之后再渲染 head 元素,
3. head 元素渲染完成之后在渲染 meta 元素,在渲染 title 元素,这样依次渲染
4. 接下来渲染 body 元素,body 元素渲染完成之后渲染 h3 元素,在渲染 p 元素,在渲染 p 元素里面的 strong 元素,在渲染 a 元素,在渲染 img 元素
这样一个一个元素渲染的,也就是说从树型结构的父元素(根元素HTML)开始依次进行渲染,这是它的整体的渲染过程,
但是这不是我们要学习的重点,我们要学习的是渲染每一个元素的时候,它是怎么渲染的?
二、渲染每个元素的前提条件
渲染每个元素的前提条件是,该元素所有的CSS属性必须有值。
就是说我们给一个元素写CSS属性的时候,不一定全部属性都写,只需要写几个想要设置的属性的就行了,
而实际上在渲染页面的时候,一个 css 属性没有值,元素是渲染不出来,都必须要全部有值,那 css 属性有多少呢?
css 属性有很多,我们打开一个网页(右键点击检查f12)
1. 随便选一个元素
2. 点击右边 computed 选项卡
3. 把 Show all 前进的钩选中(表示选中这个元素所有的css属性)
这些属性必须要全部有值,只有全部有值了之后,才能代表这个元素方方面面的显示效果( 什么文字颜色,排列方式,文字大小,是否加粗,背景颜色等等… ),
每一个css属性代表一方面的样式,只有全部的css属性全部都确定下来,浏览器才知道这个元素该怎么显示,
而我们今天要学习的是,这些css属性是怎么全部出来的。
三、属性值计算过程简介
一个元素,从一开始所有属性都没有值,到所有的属性都有值,这个计算过程叫做属性值计算过程。
不是说我们写了哪些css属性,哪些css属性才有值,不是这样的,
页面上要显示的每一个元素,必须要全部的css属性全部有值,一个属性没有值都显示不出来。
这在一次说明了,在HTML核心语义化的时候学过,一个元素如果只有HTML是根本没法显示的,
显示全部要靠CSS,哪怕我们一行CSS属性都没有写,浏览器也必须要算出所有的CSS属性值,只有算出来之后才能显示出来。
浏览器做了很的事情(这一点一定要理解)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>渲染</title> </head> <body> <div> <textarea></textarea> </div> </body> </html>
1). 渲染的时候,先计算出HTML这个元素所有的CSS属性值,算出来过后渲染HTML元素(head元素不说了)
2). 在计算body元素所有的CSS属性值,再把body元素渲染出来
3). 然后在计算div元素所有的CSS属性值,再把div渲染出来
4). 在计算div里面的textarea元素所有的CSS属性值,再把textarea元素渲染出来
浏览器就是这样一步一步,渲染每一个元素的时候,都必须要把这个元素所有的CSS属性值全部算出来,全部算出来之后才能渲染。
我们今天学的就是浏览器是怎么计算的,这个css属性是怎么从没有值到有值的,
这块了解清楚后,就非常清楚之前学的继承 和 层叠是什么时候发挥作用的了。
一个html元素有很多的属性值,属性从一开始没有值,到最后每一个属性的值都确定下来,整个的过程叫做属性值的计算过程。
四、属性值的计算有四个步骤
第一步:确定声明值,样式表中没有冲突的声明,直接作为CSS属性值
第二步:层叠冲突,对样式表有冲突的声明的使用层叠规则,确定CSS属性值
第三步:使用继承,对仍然没有值的属性,若可以继承,则继承父元素
第四部:使用默认值,对仍然没有值的属性,使用默认值
有一个h1元素,一开始所有的属性都没有值
1). 我们写了一些样式
2). 浏览器默认了一些样式
1、第一步:确定声明值
确定声明值意思是,参考样式表中( 作者样式表、浏览器默认样式表,只要是样式表都行 )没有冲突的声明,直接作为CSS属性的值
那些属性值是没有冲突的?
color: red
font-weight: bold
display: block
这三个属性是没有冲突的,没有冲突的属性,直接拿过来作为CSS的属性值
属性值计算的过程第一步很简单,就是把那些没有冲突的属性声明,无论是浏览器默认样式,还是作者写的样式,
只要没有冲突就直接拿过来,非常非常的简单。
2、第二步:层叠冲突
层叠冲突,是对样式表有冲突的声明,使用 层叠规则 确定CSS属性值,
也就是说我们学习过的层叠发生在属性值计算过程的的第二步,第一步做完之后才进行层叠
这时候看一下,哪些声明是有冲突的?
下面这些(带中滑线),声明是有冲突的,把这些声明进行层叠
怎么层叠呢( 之前学过的三步 )?
1). 比较重要性: h1{display: block; font-size: 2em; font-weight: bold;} 把浏览器默认样式去掉了
2). 比较特殊性:把特殊性比较小的去掉了
.red{color:red; font-size:40px; } 类选择器去掉
h1{ font-size:26px; } 元素选择器去掉
div h1.red{} 这个特殊性更高,有元素选择器,有类选择器,所以留下
3). 比较源次序:div h1.red{font-size:3em; font-size:30px;} 把前面的font-size:3em; 去掉,
源次序靠后的 div h1.red{ font-size: 30px; } 胜出
这步完成之后,还有css属性没有值,这个时候进入第三步
3、第三步:使用继承
使用继承,对仍然没有值的属性,若可以继承,则继承父元素
1). 继承发生在,经过了前面两个步骤之后,一些属性仍然没有值( 仍然的意思是,前面已经有值的属性就不管了 )
2). 若可以继承(背景样式不能继承,文字属性可以继承)
3). 这个时候才使用继承父元素的值,所以继承的时间点在层叠之后。
比如,h1的父元素有下面这些属性值(右边),那些属性值是可以继承过来?
1). font-size: 20px、font-weight: noraml 是不可以继承的,因为是对仍然没有值的属性,前面已经有值的就不管了
2). text-align 这个属性没有值,还跟文本相关,可以继承父元素的 text-align: center;
3). background-color 属性也没有值,背景属性不能继承
因此这一步只改变了 text-align: center;
继承 和 层叠不冲突,因为继承发生的时间点是在层叠之后,
层叠的时候已经确定了属性值就不在使用继承了,换句话说已经声明了属性值就不使用继承了,
还有很多的CSS属性没有值,这个时候进入第四步。
4、第四步:使用默认值
第四步是个大杀器,对仍然没有值的属性,全部使用默认值。
比如说背景颜色 background-color属性 的默认值就是透明 background-color: transparent; ,透明是一关键词 transparent
这样到了第四步,每一个CSS属性值全部都能确定了,因为每一个CSS属性都有默认值。
5、CSS属性的默认值
mdn里面会告诉我们,每个属性的默认值是多少,比如百度搜索关键词 width mdn
https://developer.mozilla.org/zh-CN/docs/Web/CSS/width
initial value(初始值)auto width属性的默认值是auto,表示自动的
h1元素什么样式都没有设置,他的宽度是多少?
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>H1元素宽度的默认值</title> </head> <body> <h1>Lorem</h1> </body> </html>
1). 选中h1元素
2). 点击computed表示计算过后,计算过后每一个属性都有值
3). 搜索width属性,这里算出的结果是1091px,当然这是根据自动值进行计算的
我们没有设置width属性,计算过后仍然是有值的,
再一次说明必须每个css属性都是有值的,浏览器才能确定怎么渲染。
6、面试问题
div里面有
一个a元素,
一个p元素,
div设置字体颜色为红色,
字体颜色可以继承,问a元素是不是红颜色的?
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>面试题</title> <style> div{ color: Red; } </style> </head> <body> <div> <a href="">举个例子</a> <p>p元素</p> </div> </body> </html>
字体颜色是可以继承的,下面的p元素集成了是红颜色,为什么a元素字体的颜色没有继承?
搞清楚属性值计算的过程,p元素属性值的计算过程
第一步:确认声明值 p元素本身没有声明值(没有写过p元素的样式),没有声明值进入第二步
第二步:层叠 p元素颜色没有设置,声明值都没有哪里来的冲突,第二步层叠也没有冲突
第三步:继承 第一步、第二步后,p元素颜色仍然没有值,要使用继承了。这个时候就可以把red颜色继承过来,所以p元素是红色的
a元素属性值计算过程是怎么回事呢?
1). 第一步确定声明值,凡是在样式表写了样式就是声明了,a元素有声明值,在浏览器的默认样式表里面设置了颜色 color: -webkit-link;
2). 既然a元素有声明值,在第一步就确定颜色了,他也没有冲突,也不需要层叠,
因此第一步,a元素颜色就已经确认了
3). 既然确定颜色了,就不需要继承了 color : red; 杠划掉了,
也就是说有了声明值,就不能继承了
这就是为什么a元素没有变化,因为在浏览器的默认样式表中a元素已经声明过了
五、两个特殊的CSS取值
inherit :手动(强制)继承,表示将父元素的值取出应用到该元素上
initial : 初始值,将该属性设置为默认值
1、inherit
A元素的小技巧
在写重置样式的时候,希望把a元素样式重置一下,怎么重置呢?
比如,希望a元素没有下划线,然后颜色继承父元素。
1、没有下划线:
希望a元素没有下划线简单,去掉下划线简单 text-decoration: none;
第一步,确定声明值,作者样式表 和 默认样式有冲突
第二步,层叠冲突,重要性作者样式表胜出
2、颜色继承父元素
希望颜色继承父元素,但是继承是发生在第三步的,前面两步已经把颜色确定下来,就不会发生继承了,
这个时候可以使用强制继承,这里可以声明一下颜色,颜色是什么不知道,反正来自父元素
强制继承写法是 color: inherit ,用一个单词inherit意思是继承。
a{ text-decoration: none; color: inherit; // 强制使用父元素的值 }
这样a元素是红色的了,a元素为什么是红色的了?
1). 第一步,确认声明值,没有冲突颜色直接拿过去,
color已经有冲突了,color: inherit 第一步没有颜色不管
2). 第二步,层叠冲突,作者样式表 比浏览器的 默认样式表重要,作者样式表胜出,
在第二步color属性就已经有值了,值是inherit ,值是来自父元素的颜色的值
渲染的过程是从上到下,所以父元素所有值已经确定下来了,用这个单词inherit 去拿父元素的颜色值,
color属性的颜色已经有值了,第三步的继承不会发生了
强制继承就是声明一个属性值 inherit ,在一步确认声明值 或者是 第二步层叠冲突,完成属性值的确定,而不是等到第三步继承这个步骤在确定,相当于把继承给提前了。
inherit 这个关键字的好处是,有些不能继承的属性也可以使用这个关键字,强制使用父元素的值
/* 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; } /* 重置a元素 */ a{ text-decoration: none; color: inherit; }
2、initial
initial初始值的例子
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>initial初始值</title> <style> div{ width: 100px; height: 100px; background-color: Red; } .mydiv{ background-color: initial; /* div默认背景又是透明的了 */ } </style> </head> <body> <div class="mydiv"></div> </body> </html>
我们知道background背景颜色的默认是transparent background: transparent;
但是有些属性不知道他的默认值是什么,这个时候只需要使用一个关键字initial,表示直接使用这个属性的默认值 background: initial;