关于浏览器的渲染过程

对于这个过程,我是真的看了好多资料都没能达到很是透彻的理解,如下是我所能了解并理解的一些:特此整理并记录下来,仅供本身的学习啦javascript

关于浏览器的一些基础知识css

浏览器的主要功能是向服务器发出请求,在浏览器窗口中显示咱们所选择的的网络资源,咱们所选择的网络资源通常是指html文档,PDF,图片或其余类型的东西(动态文件之类的),资源的位置由用户使用的URL(统一资源定位符)指定。html

浏览器解释并解释html文件的方式是在html和css规范中指定的,这些规范由W3C进行维护,可是这么多年过去了,各大浏览器并无彻底听从这些规范,同时还在开发本身独有的扩展程序,这对前端开发人员来讲就真的太苦逼了,这种兼容性问题实在头疼,现在,大多数浏览器是或多或少的听从W3C的规范。前端

用过各类浏览器的确定也注意到它们彼此之间是有不少相同的元素的,其中包括:html5

输入栏(URL)java

前进和后退node

书签设置linux

刷新按钮和中止加载按钮web

返回主界面的按钮正则表达式

各浏览器也都还有着本身各自的功能,好比Firefox的下载管理器之类的。

浏览器的高层结构

 

1.用户界面-包括地址栏,前进、后退按钮书签单等,除了浏览器主窗口的显示的页面外,其余显示的各个部分都属于用户界面。

2浏览器引擎-在用户界面和呈现引擎之间传送指令。

3呈现引擎-负责显示请求的内容。若是请求的内容是html,它就解析html和css内容,并将解析后的内容显示在屏幕上。

4.网络-用于网络调用,好比http请求。这个接口与平台无关,并为全部平台提供底层实现。

5.用户界面后端-用于绘制基本的窗口小部件,好比组合框和窗口,其公开了与平台无关的通用接口,而在底层使用操做系统的用户界面方法

6.Javascript解析器,用于解析和执行javascript代码。

7.数据存储,也就是咱们的浏览器的存储,像cookie啦,localstroage啦,sessionstorage(讲到这我又想回顾一下这三个东西的区别了,先说一下,这三个都是存储在浏览器端的,主要是存储的大小不一样,数据有效期不一样,仍是改天再另外撸一篇吧!)h5定义了‘网络数据库’,这是一个完整可是轻便的浏览器内存数据库。

值得注意的是,和大多数浏览器不一样,Chrome浏览器的每一个标签页都对应一个呈现引擎实例。每一个标签页都是一个独立的进程(那么这个就是它完虐各大浏览器的缘由之一???,我猜的)

呈现引擎

呈现引擎的做用很明显就是呈现咯,也就是在浏览器的屏幕上显示请求的内容。

默认状况下,呈现引擎可显示html和XML文档与图片。经过插件(浏览器的扩展程序),还能够显示其余类型的内容;使用PDF查看器插件就能显示PDF文档。可是他的主要用途是:显示使用css格式化的html内容和图片。

那么呈现引擎也有好几种,Firefox使用的是Gecko,这是mozilla公司本身开发的呈现引擎,Chrome和safair都是webkit。

webkit是一种开放源代码的呈现引擎,起初用于linux平台,随后由apple公司修改,从而它是支持苹果机和windows的。

接下来看主流程

接下来重点来啦:

呈现引擎将开始解析html文档,并将各标记逐个转化成内容树上的DOM节点。同时会解析外部css文件以及样式元素中的样式数据。html中这些带有视觉指令的样式信息将用于建立另外一个树结构,我叫它渲染树,也有人叫它呈现树。

渲染树包含多个视觉属性的矩形,这些矩形的排列顺序就是他们将在屏幕上显示的顺序。

渲染树构建完毕后,进入布局处理阶段,也就是为每一个节点分配一个应出如今屏幕上的确切坐标,下一个阶段是绘制--这时呈现引擎会遍历渲染树,由用户界面后端将每一个节点绘制出来。

须要着重指出的是,这是一个渐进的过程,为了达到更好的用户体验,呈现引擎会力求尽快将内容显示在屏幕上,它没必要等到整个html文档解析完毕,就会开始构建渲染树和设置布局,在不断的接收和处理来自网络的其他内容的同时,呈现引擎将会部份内容解析并呈现出来。

虽然二者的术语不一样,但总体流程是基本相同的。

Gecko将视觉格式化元素组成的树称为框架树。每一个元素都是一个框架。webkit则是呈现树,它由呈现对象组成,对于元素的位置,webkit使用的术语是布局,而Gecko称之为重排。对于链接DOM节点和可视化信息从而建立呈现树的过程,webkit称为附加,有一个细微的非语义化差异,就是Gecko和html与DOM树之间还有一个称为内容槽的层,用于生成DOM元素。

接下来逐一论述流程中的每个部分:

解析-综述

解析是呈现引擎中很是重要的一个环节,所以咱们要更深刻地理解。首先,先来介绍一下解析。

解析文档是指将文档转化成为有意义的结构,也就是可以让代码理解和使用的结构。解析获得的结果一般是表明了文档结构的节点数,它称为解析树或者语法树。

讲了这么久的树,那么什么是树,来看:

 语法:解析是以文档所听从的语法规则(编写文档所用的语言或格式)为基础的,全部能够解析的格式都必须对应肯定的语法(由词汇和语法规则构成)。这称为与上下文无关的语法。人类语言并不属于这样的语言,所以没法用常规的解析技术进行解析。

(以上这段,我目前都还不是很懂,之后回来看看吧)

解析器和词法分析器的组合

解析的过程能够分为两个子过程:词法分析和语法分析。

词法分析是将输入内容分割成大量标记的过程。标记是语言中的词汇,即构成内容的单位,在人类语言中,它至关于语言字典中的单词。

语法分析是应用语言的语法规则的过程

解析器一般将解析工做分给两个组件来处理:词法分析器(有时候也叫标记生成器),负责将输入内容分解成一个个有效的标记;而解析器负责根据语言的语法规则来分析文档结构,从而构建解析树。词法分析器知道如何将无关的字符(好比空格和换行符)分离出来。

解析是一个迭代的过程。一般,解析器会向词法分析器请求一个新标记,并尝试将其与某条语法规则进行匹配。若是发现了匹配规则,则解析器会将一个对应于标记的节点添加到解析树中,而后继续请求下一个标记。

若是没有规则可匹配,解析器就会将标记存储到内部,并继续请求标记,直至找到可与全部内部存储的标记匹配的规则。若是找不到任何匹配规则,解析器就会引起一个异常。这意味着文档无效,包含语法错误。

翻译:

不少时候,解析树不是最终产品。解析一般是在翻译过程当中使用的,而翻译是指将输入文档转换成另外一种格式。编译就是这样一个例子。编译器可将源代码编译成机器代码,具体过程是首先将源代码解析成解析树,而后将解析树翻译成机器代码文档。

解析示例:

以前已经看了经过数学表达式简历了解析树。如今,让咱们试着定义一个简单的数学语言,用来演示解析的过程。

1:构成语言的语法单位是表达式,项和运算符。

2.咱们用的语言能够包含任意数量的表达式。

3.表达式的定义是:一个项接一个运算符,而后再接一个项。

4.运算符是加号或减号。

5.项是一个整数或一个表达式。

好了,能够分析 2+3—1了

匹配语法规则的第一个子串是2,而根据第五条词法规则,这是一个项。匹配语法规则的第二个子串是2+3,而根据第三条规则,这是一个表达式。下一个匹配项已经到了输入的结束。2+3-1是一个表达式,由于咱们已经知道2+3是一个项,这样就符合第三条条规则。2++不与任何规则匹配,所以是无效的输入。

好像有点儿懂了

解析器类型

有两种基本类型的解析器:自上而下解析器和自下而上解析器。直观来讲,自上而下的解析器从语法的高层结构出发,尝试从中找到匹配的结构。而自下而上的解析器从底层规则出发,将输入内容转化为语法规则,直至知足高层规则。

接下来能够看看这两种解析器会如何解析咱们的示例:

自上而下的解析器会从高层开始:首先将2+3标识为一个表达式,而后将2+3-1标识为一个表达式(标识表达式的过程涉及到匹配其余规则,可是起点是最高级别的规则,懂)

自下而上的解析器将扫描输入内容,找到匹配的规则后,将匹配的输入内容替换成规则。如此继续替换,直至输入内容的结尾。部分匹配的表达式保存在解析器的堆栈中。

这种自下而上的解析器称为移位归约解析器,由于输入在向右移位(设想有一个指针从输入内容的开头移动到结尾),而且逐渐归约到语法规则上。

不懂

 自动生成解析器

有一些工具是能够帮助生成解析器的,它们称为解析器生成器。咱们只要提供咱们所用的语法(语法规则和词汇),它就会生成相应的解析器。建立解析器须要对解析器有深入的理解,而人工建立优化的解析器并非一件容易的事情,因此解析器生成器是很是实用的。

webkit实用了两种很是有名的解析器生成器:用于建立词法分析器的flex以及用于建立解析器的bison。flex的输入是包含标记的正则表达式定义的文件,bison的输入是采用BNF格式的语言语法规则。

HTML解析器

html解析器的任务是将html标记解析成解析树。

html语法定义

html的词汇和语法在W3C组织建立的规范中进行了定义。当前的版本是html5.

非与上下文无关的语法

正如咱们在解析过程的简介中已经了解到,语法能够用BNF等格式进行正式定义。

很遗憾,全部的常规解析器都不适用于HTML(啊,我才知道)。html并不能很容易地用解析器所需的与上下文无关的语法来定义。有一种能够定义html的正规格式:DTD(document type definition),但它不是与上下文无关额语法。

这起初看起来很奇怪:html与XML很是类似。有不少XML解析器可使用。html存在一个XML变体(XHTML),那么有什么大的区别呢,区别在于html的处理更为“宽容”,它容许你省略某些隐式添加的标记,有时候还能省略一些起始或结束的标记等,和XML严格的语法不一样,html总体来看是一种“软性”的语法。

显然,这种看上去细微的差异实际上却带来了巨大的影响。一方面,这是HTML如此流行的缘由:它能包容咱们的错误;简化网络开发。另外一方面,这使得它很难编写正式的语法。归纳的说,html没法很容易地经过常规解析器解析(由于它的语法不是与上下文无关的语法),所以也没法经过XML解析器来解析。

 

HTML DTD

html的定义采用了DTD格式,这个格式可用于定义SGML族的语言。(什么鬼)。它包含了全部容许使用的元素及其属性和层次结构的定义。如上文所述,HTML DTD没法构成与上下文无关的语法。

DTD存在一些变体。严格模式彻底遵循html规范,而其余模式可支持之前的浏览器多使用的标记。这样作的目的是确保向下兼容一些旧版本的内容。最新的严格模式DTD在这http://www.w3.org/TR/html4/strict.dtd 

 

DOM

解析器的输出“解析树”是由DOM元素和属性节点构成的树结构。DOM是文档对象模型的缩写,它事HTML文档的对象表示,同时也是外部内容(css js)与html元素之间的接口。

解析算法

HTML没法用常规的自上而下或自下而上的解析器进行解析。缘由在于:

1.语言的宽容本质。

2.浏览器从来对一些常见的无效html用法采起包容的态度。

3.解析过程须要不断地反复。源内容在解析过程当中一般不会改变,可是在HTML中,脚部标记若是包含document.write,就会添加额外的标记,这样解析过程实际上就更改了输入内容。

因为不能使用常规的解析过程,浏览器就建立了自定义的解析器来解析HTML。http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html,这个地址是html5规范详细德描述了解析算法。此算法由两个阶段组成:标记化和树构建。

标记化是词法分析过程,将输入内容解析成多个标记。HTML标记包括起始标记,结束标记,属性名和属性值。标记生成器识别标记,传递给树构造器,而后接受下一个字符以识别下一个标记;如此反复知道输入结束。

标记化算法

该算法的输出结果是html标记。该算法使用状态机来表示。每个状态接收来自输入信息流的一个或多个字符,并根据这些字符更新下一个状态。当前标记化状态和树结构状态会影响下一个状态的决定。这意味着,即使接收的字符相同,对于下一个正确的状态也会产生不一样的结果,具体取决于当前的状态。该算法至关复杂,没法详述,因此咱们经过一个简单的示例来理解。

将下面的html代码标记化:

<html>

<body>

hello xiaoai

</body>

</html>

初始化时数据状态。遇到字符<时,状态更改成“标记打开状态”。接收一个a-z字符会建立“起始标记”,状态更改成“标记名称状态”。这个状态会一直保持到接收>。在此期间接收的每一个字符都会附加到新的标记名称上。

遇到>标记时,会发送当前的标记,状态改回“数据状态”。<body>标记也会进行一样的处理。目前html和body标记均已发出。如今咱们回到“数据状态”。接收到hello xiaoai 中的h字符时,将建立并发送字符标记,直到接收</body>中的<。咱们将为hello xiaoai 中的每个字符都发送一个字符标记。(不错,讲得好详细,<摊手>)

如今回到“标记打开状态”。接收下一个输入字符/时,会建立 end tag token 并改成“标记名称状态”。咱们会再次保持这个状态,直到回收>.而后将发送新的标记,并回到“数据状态”。</html>输入也会一样的处理。

 

树构建算法

    在建立解析器的同时,也会建立document对象。在树构建阶段,以document为根节点的DOM树也会不断进行修改,向其中添加各类元素,标记生成器发送的每一个节点都会由树构建器进行处理。规范中定义了每一个标记所对应的dom元素。这些元素会在接收到相应的标记时建立。这些元素不只会添加到dom树中,还会添加到开放元素的堆栈中。此堆栈用于纠正嵌套错误和处理未关闭的标记。其算法也能够用状态机来描述。这些状态称为“插入模式”。

仍是上面的代码,来看看树构建过程。

<html>

<body>

hello xiaoai

</body>

</html>

树构建阶段的输入是一个来自标记化阶段的标记序列。第一个模式是“initial mode”。接收html标记后转为“before html”模式,并在这个模式下从新处理此标记。这样会建立一个htmlelement元素,并将它附加到document的根对象上。

而后状态改成“before head”。此时咱们接收“body”标记。即便咱们的示例中没有“head”标记,系统也会隐式建立一个html headelement,并将它附加的树中。

如今进入了“ in head”模式,而后转入“after head”模式。系统对body 标记进行从新处理,建立并插入HTML bodyelement ,同时模式转变为“body”

如今,接收由“hello xiaoai”字符串生成的一系列字符标记。接收第一个字符时会建立并插入“Text”节点,而其余字符也将附加到该节点。

接收body结束标记会触发“after body”模式。如今咱们将接收html结束标记,而后进入“after after body”模式。接收到文件结束标记后,解析就此结束。

解析结束后

   在此阶段,浏览器会将文档标注为交互状态,并开始解析那些处于“deferred”模式的脚本,也就是那些应在文档解析完成后才执行的脚本。而后,文档状态设置为“完成”,一个“加载”事件将随之触发,连接:http://www.w3.org/TR/html5/syntax.html#html-parser

浏览器的容错机制

咱们在浏览html网页时历来不会看到“语法无效”的错误,这是由于浏览器会纠正任何无效内容,而后继续工做。

HTML5 规范了一部分这样的要求,webkit在html解析器类的开头注释对此做了很好的归纳:

浏览器对标记化输入内容进行解析,以构建文档树。若是文档的格式正确,就直接进行解析。

遗憾的是,咱们不得不处理不少格式错误的html文档,因此解析器必须具有必定的容错性。

咱们至少可以处理如下的错误状况:

1明显不能在某些外部标记中添加的元素。此状况下,咱们应该关闭全部的标记,直到出现禁止添加的元素,而后再加入该元素。

2.咱们不能直接添加的元素。这极可能是网页做者忘记添加了其中的一些标记(或者其中的标记是可选的)。这些标签可能包括:HTML head body tbody tr td li。

3.向inline元素内添加block 元素。关闭全部inline元素,直到出现下一个较高级的block元素。

4.若是这样仍然无效,可关闭全部元素,直到能够添加元素为止,或者忽略该标记。

以上这么多都在讲html的解析,接下来看看css的解析

css 解析

和html不一样,css是上下文无关的语法,可使用各类解析器进行解析。事实上,css规范定义了css的词法和语法。连接:http://www.w3.org/TR/CSS2/grammar.html

webkit css解析器

webkit使用flex和bison解析器生成器,经过css语法文件自动建立解析器。正如咱们以前在解析器的介绍中所说,bison会建立自下而上的移位规约解析器。Firefox使用的是人工编写的自上而下的解析器。这两种解析器会将css文件解析成stylesheet对象,且每一个对象都包含css规则。css规则包含选择器和声明对象,以及其余与css语法对应的对象。

不太懂

接下来脚本!

处理脚本和样式表的顺序

脚本

     网络的模型是同步的,网页做者但愿解析器遇到<script>标记时当即解析并执行脚本,文档的解析将中止,直到脚本执行完毕。若是脚本是外部的,那么解析过程会中止,直到从网络同步抓取资源完成后再继续。此模型已经用了不少年了,也在HTML4和html5规范中进行了指定。做者也能够将脚本标注为“defer”,这样它就不会中止解析文档,而是等到解析结束后才执行。h5增长了一个选项,可将脚本标记为异步,以便其余线程解析和执行。

预解析

   webkit和Firefox都进行了这项优化。在执行脚本时,其余线程会解析文档的其他部分,找出并加载须要经过网络加载的其余资源。经过这种方式,资源能够在并行链接上加载,从而提升整体速度,可是,预解析器不会修改DOM树,而是将这项工做交由主解析器处理;预解析器只会解析外部资源(js,css,图片)的引用。

样式表

    另外一方面,样式表有着不一样的模型。理论上来讲,应用样式表不会更改dom树,所以彷佛没有必要等待样式表并中止解析。但这涉及到一个问题,就是脚本在文档解析阶段会请求样式信息,若是当时尚未加载和解析样式,脚本就会得到错误的回复,这样显然会产生不少问题。这看上去是一个非典型案例,可是事实上很是广泛。Firefox在样式表加载和解析的过程当中,会禁止全部的脚本。而对于webkit而言,仅当脚本尝试访问样式属性可能受还没有加载的样式表影响时,它才会禁止该脚本。

 

呈现树的构建

     在DOM树构建的同时,浏览器还会构建另外一个树结构:呈现树。这是可视化元素按照其显示顺序而组成的树,也是文档的可视化表示。它的做用是按照正确顺序绘制内容。

Firefox 将呈现树中的元素称为“框架”。webkit使用的术语是呈现器或呈现对象。

呈现器知道如何布局并将自身及其子元素绘制出来。

webkit的呈现对象类是全部呈现器的基类。

class RenderObject{
   virtual void layout();
   virtual void paint(PaintInfo);
   virtual void rect repaintRect();
   Node* node;  //the DOM node
   RenderStyle* style;  // the computed style
   RenderLayer* containgLayer; //the containing z-index layer
}
每个呈现器都表明了一个矩形的区域,一般对应于相关的css框,这一点在css2中有描述,它包含宽度,高度和位置等几何信息。
框的类型会受到与节点相关的“display”样式属性的影响。元素类型也是考虑因素之一,例如表单控件和表格都对应特殊的框架。若是一个元素须要建立特殊的呈现器,就会替换createRender方法,在webkit中,呈现器所指向的样式包含了一些和几何无关的信息。
呈现树和DOM树的区别
 
    呈现器是和DOM元素相对应的,但不是一一对应。非可视化的dom元素不会插入到呈现树中,例如“head”元素。若是元素的display属性值为none,那么也不会出如今呈现树中(可是visibility属性值为hidden的元素是会显示在呈现树中的)
有一些DOM元素对应多个可视化对象,他们每每是具备复杂结构的元素,没法用单一的矩形来描述。例如“select”元素有三个呈现器:一个用于显示区域,一个用于下拉列表框,还有一个用于按钮。若是宽度不够,文本没法在一行中显示而分为多行,那么新的行也会做为新的呈现器而添加。
另外一个关于多呈现器的例子是格式无效的HTML。根据css规范,inline元素只能包含block元素或inline元素中的一种。若是出现了混合内容,则应建立匿名的block呈现器,以包裹inline元素。
有一些呈现对象对应于dom节点,但在树中所在的位置与dom节点不一样。浮动定位和绝对定位元素就是这样,他们处于正常流以外,放置在树中的其余地方,并映射到真正的框架,而放在原位的是占位框架。
 
构建呈现树的流程
 
      在Firefox中,系统会针对DOM更新注册展现层,做为侦听器。展现层将框架建立工做委托给frameconstructor,由该构造器解析样式并建立框架。
      在webkit中,解析样式和建立呈现器的过程叫“附加”。每一个dom节点都有一个“attach”方法。附加是同步进行的,将节点插到dom树须要调用新的节点“attach”方法。
      处理HTML和body标记就会构建呈现树根节点。这个根节点呈现对象对应于css规范中所说的容器block,这是最上层的block,包含了其余全部的block。它的尺寸就是视口,即浏览器窗口显示区域的尺寸。Firefox称之为viewportframe,而webkit称之为renderview。这就是文档所指向的呈现对象。呈现树的其他部分以dom树节点插入形式来构建。
 
 
样式计算
   
      构建呈现树时,须要计算每个呈现对象的可视化属性。这是经过计算每一个元素的样式属性来完成的。样式包括来自各类来源的样式表,inline样式元素和html中的可视化属性(bgcolor)。其中后者将通过转化以匹配css样式属性。
 
       样式表的来源包括浏览器的默认样式表,由网页做者提供的样式表以及由浏览器用户提供的用户样式表(浏览器容许你本身定义喜欢的样式,Firefox中,用户能够将本身喜欢的样式表放在“Firefox profile”文件夹下)
 
   样式计算存在如下难点:
1.样式数据是一个超大的结构,存储了无数的样式属性,这可能形成内存问题。
2.若是不进行优化,为每一元素查找匹配的规则会形成性能问题。要为每个元素遍历整个规则表来寻找匹配规则,这是一项浩大的工程。选择器会具备很复杂的结构,这就会致使某个匹配过程一开始看起来极可能是正确的,但最终发现实际上是徒劳的,必须尝试其余匹配路径。
好比 :如下这个组合选择器:
div div div div{。。。}
这意味着 规则使用于三个div元素的子代div。若是你要检查规则是否适用于某个指定的div元素,应选择树上一条向上路径进行查询。你要向上遍历节点树,结果发现只有两个div,并且规则不适用。而后你必须尝试树中其余的路径。
3.应用规则涉及至关复杂的层叠规则(用于定义这些规则的层次)
看看浏览器是怎么处理这些问题
共享样式数据
 
webkit 节点会引用样式对象(renderstyle)。这些对象在某个状况能够由不一样节点共享。这些节点是同级关系,而且:
1.这些元素必须处于相同的鼠标状态(例如,不容许其中一个是:hover,而另外一个不是)
2.任何元素都没有ID
3.标记名称应匹配
4类属性应匹配
5.映射属性的集合必须彻底相同的
6.连接状态必须匹配
7.焦点状态必须匹配
8.任何元素必须匹配
9元素中不能有任何inline样式属性
10.不能使用任何同级选择器。
 
是否是很难懂?<摊手>
直接看布局吧
 
布局
   呈现树在建立完成并添加到呈现树时,并不包含位置和大小信息。计算这些值得过程称为布局或重排。
  HTML采用基于流的布局模式,这意味着大多数状况下只要一次遍历就能计算出几何信息。处于流中靠后位置元素一般不会影响靠前元素的几何特征,所以布局能够按从左到右,从上至下遍历文档。可是也有例外状况,好比HTML表格的计算就须要不止一次的遍历。
   坐标系是相对于根框架而创建的,使用的是上左标和左坐标。
布局是一个递归的过程,它从根呈现器(<html>)开始,而后递归遍历部分或全部的框架层次结构,为每个须要计算的呈现器计算几何信息。
全部的呈现器都有一个“layout”或者“reflow”方法,每个呈现器都会调用其须要进行布局的子代的layout方法。
 
 
定位方案
1.普通:根据对象在文档中的位置进行定位,也就是说对象在呈现树中的位置和它在dom树中的位置类似,并根据其框架类型和尺寸进行布局。
2.浮动:对象先按照普通流进行布局,而后尽量地项右或向左移动。
3.绝对:对象在呈现树中的位置和它在dom树中的位置不一样。
定位方案有position属性和float属性设置的。
若是值时static和relative,就是普通流。
若是值时absolute和fixed,就是绝对定位。
static定位无需定义位置,而是使用默认定位。对于其余方案,网页做者须要指定位置:top,bottom,left,right。
框的布局方式是由如下因素决定的:
框类型
框尺寸
定位方案
外部信息,例如图片大小和屏幕大小
 
 
框类型:
block框:造成一个block,在浏览器窗口拥有其本身的矩形区域。
inlinne框:没有本身的block,可是位于容器block内。
block采用的是一个接一个的垂直格式,而inline采用的是水平格式。
inline框放置在行中或行框中,这些行至少和最高的框同样高,还能够更高,当框根据“底线”对齐时,这意味着元素的底部须要根据其余框中非底部的位置对齐。若是容器宽度不够,inline元素会分为多行放置,在段落中常常发生这种状况。
 
 
 
分层展现
z-index css属性指定的。它表明了框的第三个维度,也就是沿z轴方向的位置。
 
看到这已经头晕晕了,但还得往下:
 
 
看看如何简易的描述浏览器的渲染过程
 
1.浏览器会将HTML解析成一个dom树,dom树的构建过程是一个深度遍历过程:当前节点的全部子节点都构建好后才会去构建当前节点的下一个兄弟节点。
2.将css解析成css规则树。
3.根据DOM树和css规则树来构造rendering树(渲染树或呈现树)rendering树并不等于DOM树,前面讲过啦。
4.有了渲染树,浏览器已经能知道网页中有哪些节点,各个节点的css定义以及它们的从属关系,下一步操做称之为“layout”,就是计算出每一个节点在屏幕中的位置
5.在下一步就是绘制,即遍历rendering树,并使用UI后端绘制每一个节点。
上述这个过程是逐步完成的,为了更好的用户体验,渲染引擎会尽量早的将内容呈现到屏幕上,并不会等到全部html都解析完成后再去构建和布局rendering树,它是解析完一部份内容就显示一部份内容,同时,可能还在经过网络下载其余内容。
 
 总的来讲:浏览器的加载,解析,渲染过程,我概括以下
1。输入网址
2.浏览器查找域名的IP地址
3.浏览器给web服务器发送一个http请求
4.  网站服务的永久重定向响应(?)
5.浏览器跟踪重定向地址。
如今浏览器知道了要访问的正确地址,因此它会发送另外一个获取请求
6.服务器处理请求,服务器接收到获取请求,而后返回一个响应。
7.服务器返回一个html响应
8.浏览器开始显示html(这里就会发生上面的解析啦,渲染啦等过程)
9.浏览器发送请求,以获取嵌入在html中的对象,就是再次发送http请求以获取js,css,图片等资源(这个过程会再次发生dns域名查询,发送请求,重定向等等这些步骤)
 
 
渲染引擎在取得内容后:
解析html以构建DOM树-->构建渲染树rendering树-->布局(重排)rendering树-->绘制rendering树