html
html文件的解析执行顺序?
参考1
参考2很重要
参考3
参考4
参考5
参考5
正常情况:
0、加载整体html文件
1、至上而下解析html
2、解析html建立dom树,遇到诸如
、
<script>
<link>
等标签时,就会去下载相应内容,并解
析、执行。如果是
<link>
标签,解析css构建CSSOM树
4、DOM和CSSOM结合生成render树
5、布局render树(Layout/reflow),负责各元素尺寸、位置的计算
6、绘制render树(paint),绘制页面像素信息
7.浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上。
从下载角度讲
当HTML解析器遇到
标签,开始下载时,只存在一种阻塞情况,就是
<script>、<link>、<img>
标签会阻止
<script>
资源下载,其余
<img>
<script>、<link>
相互之间下载没有影响。
外部脚本与外部样式是并行加载(即在 下载 阶段,
互不影响,符合上述结论),但直到外部样式加载完毕,外部脚本才开始执行(即外部样式的下载,虽然不会影响外部脚本的下载,但会影响脚本的运行)
<script>、<link>
从解析角度讲
下载完成之后,就会运行解析相应的JS文件或者CSS文件,运行JS文件需要JS引擎线程,前面提到,JS引擎和GUI时互斥的,所以在 解析 的角度讲,JS引擎运行,会阻塞GUI,即阻止页面渲染。
css文件不会阻塞HTML解析,但是会阻塞渲染,导致css文件未下载完成之前已经解析好html也无法先显示出来。
总结
css下载和js下载可并行,但要等css加载完在执行js,执行js时html解析被阻塞。css不阻塞html的解析但会阻塞渲染
script有async defer
defer-IE独有
原生的defer思路:为标签配置一个defer属性(这是个bool属性,配置之后表示为true),这表明我们知道脚本内没有类似document.write的方法,此时标签内的脚本就会并行的加载,并且在DOM解析完毕之后(即document.readyState变为inactive之后和DOMContentLoaded事件触发之前),将脚本执行。注意:不同脚本的执行顺序,是按照不同脚本相应的
<script>
在HTML中出现的顺序决定的。
<script>
async
async 属性表示异步执行引入的 JavaScript,与 defer 的区别在于,如果已经加载好,就会开始执行——无论此刻是 HTML 解析阶段还是 DOMContentLoaded 触发之后。需要注意的是,这种方式加载的 JavaScript 依然会阻塞 load 事件。换句话说,async-script 可能在 DOMContentLoaded 触发之前或之后执行,但一定在 load 触发之前执行。
defer 与相比普通 script,有两点区别:
载入 JavaScript 文件时不阻塞 HTML 的解析,执行阶段被放到 HTML 标签解析完成之后。
在加载多个JS脚本的时候,async是无顺序的加载,而defer是有顺序的加载。
三种方式适合什么时候用
growingwiththeweb 推荐优先级依次是 async defer normal。。
1、当你的js是个独立的模块且不依赖任何js,使用 async;
2、如果你的js依赖其他js或者被其他js 依赖,使用 defer;
3、如果你对js文件很小且被 async script 依赖,使用正常模式的script且放在async script 前面。
js css放置顺序
参考文献
共识:
JS尽量放在HTML底部。
CSS尽量放在HTML头部。
内联js放外链css之前
JS放在底部是为了防止阻塞DOM的解析,CSS放在头部是为了尽早完成CSSOM的构建,从而尽早paint页面。
假如我们有一段内联的、需要提前加载的、JS统计逻辑代码,很自然的,会把内联JS放在head里。那么是放在css前面,还是后面呢?1、浏览器解析HTML的时候,会对整个HTML进行『preload scanner』,提前发起网络请求,下载外链资源,并不是解析到对应标签才会进行下载。而外链下载这个过程是由浏览器进程的网络线程完成的,不会阻塞当前渲染器进程的主线程逻辑。
2、JS会阻塞HTML的解析。内联JS在CSS前面的时候,执行内联JS可以和网络请求并行执行,执行完内联JS后会继续解析HTML,并且在CSS文件下载完成后,选择合适的时机进行渲染。而内联JS在CSS后面的时候,由于考虑到内联JS可能会修改CSSOM,所以主线程会暂停,直到CSS下载完成,生成CSSOM后,才会继续执行内联JS、解析HTML.
总结:内联js放外链css之前
在WebKit中,预加载扫描器指的是一个副解析器,当HTML主解析器被一个同步的script标签阻塞时,预加载扫描器就会启动.然后,它会马上找出接下来即将需要获取的资源(比如样式表,脚本,图片等资源)的URL,然后尽可能早的发起网络请求,而不用等到主解析器恢复运行,从而提高了整体的加载时间
除了HTML文件,网站通常还会使用到一些诸如图片,CSS样式以及JavaScript脚本等子资源。这些文件会从缓存或者网络上获取。主线程会按照在构建DOM树时遇到各个资源的循序一个接着一个地发起网络请求,可是为了提升效率,浏览器会同时运行“预加载扫描”(preload scanner)程序。如果在HTML文档里面存在诸如\或者\这样的标签,预加载扫描程序会在HTML解析器生成的token里面找到对应要获取的资源,并把这些要获取的资源告诉浏览器进程里面的网络线程。
浏览器的回流与重绘 (Reflow & Repaint)
浏览器使用流式布局模型 (Flow Based Layout)。
有了 RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。
回流
当 Render Tree 中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
页面首次渲染
浏览器窗口大小发生改变
元素尺寸或位置发生改变
元素内容变化(文字数量或图片大小等等)
元素字体大小变化
添加或者删除可见的 DOM 元素
激活 CSS 伪类(例如::hover)
查询某些属性或调用某些方法
重绘
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility 等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
如何避免回流
CSS:
避免使用 table 布局。
尽可能在 DOM 树的最末端改变 class。
避免设置多层内联样式。
将动画效果应用到 position 属性为 absolute 或 fixed 的元素上。
避免使用 CSS 表达式(例如:calc())。
Javascript:
避免频繁操作样式,最好一次性重写 style 属性,或者将样式列表定义为 class 并一次性更改 class 属性。
避免频繁操作 DOM,创建一个 documentFragment,在它上面应用所有 DOM 操作,最后再把它添加到文档中。
也可以先为元素设置 display: none,操作结束后再把它显示出来。因为在 display 属性为 none 的元素上进行的 DOM 操作不会引发回流和重绘。
避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
html5
html5新特性
webworker
WebWorker,JS的多线程?
前文中有提到JS引擎是单线程的,而且JS执行时间过长会阻塞页面,那么JS就真的对cpu密集型计算无能为力么?
所以,后来HTML5中支持了Web Worker。
MDN的官方解释是:
Web Worker为Web内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面
一个worker是使用一个构造函数创建的一个对象(e.g. Worker()) 运行一个命名的JavaScript文件
这个文件包含将在工作线程中运行的代码; workers 运行在另一个全局上下文中,不同于当前的window
因此,使用 window快捷方式获取当前全局的范围 (而不是self) 在一个 Worker 内将返回错误
这样理解下:
创建Worker时,JS引擎向浏览器申请开一个子线程(子线程是浏览器开的,完全受主线程控制,而且不能操作DOM)
JS引擎线程与worker线程间通过特定的方式通信(postMessage API,需要通过序列化对象来与线程交互特定的数据)
所以,如果有非常耗时的工作,请单独开一个Worker线程,这样里面不管如何翻天覆地都不会影响JS引擎主线程,
只待计算出结果后,将结果通信给主线程即可,perfect!
而且注意下,JS引擎是单线程的,这一点的本质仍然未改变,Worker可以理解是浏览器给JS引擎开的外挂,专门用来解决那些大量计算问题。
其它,关于Worker的详解就不是本文的范畴了,因此不再赘述。
WebWorker与SharedWorker
既然都到了这里,就再提一下SharedWorker(避免后续将这两个概念搞混)
WebWorker只属于某个页面,不会和其他页面的Render进程(浏览器内核进程)共享
所以Chrome在Render进程中(每一个Tab页就是一个render进程)创建一个新的线程来运行Worker中的JavaScript程序。
SharedWorker是浏览器所有页面共享的,不能采用与Worker同样的方式实现,因为它不隶属于某个Render进程,可以为多个Render进程共享使用
所以Chrome浏览器为SharedWorker单独创建一个进程来运行JavaScript程序,在浏览器中每个相同的JavaScript只存在一个SharedWorker进程,不管它被创建多少次。
看到这里,应该就很容易明白了,本质上就是进程和线程的区别。SharedWorker由独立的进程管理,WebWorker只是属于render进程下的一个线程
语义化
语义化优点:
易于用户阅读,样式丢失的时候能让页面呈现清晰的结构。
有利于SEO,搜索引擎根据标签来确定上下文和各个关键字的权重。
方便其他设备解析,如盲人阅读器根据语义渲染网页
有利于开发和维护,语义化更具可读性,代码更好维护,与CSS3关系更和谐。
css
css选择器的优先级?
1、位于标签里的
<head/>
<style/>
中所定义的CSS拥有最高级的优先权。
2、第二级的优先属性由位于
标签中的
<style/>
@import
引入样式表所定义。
3、第三级的优先属性由
<link/>
标签所引入的样式表定义。
4、第四级的优先属性由
标签所引入的样式表内的
<link/>
@import
导入样式表定义。
5、第五级优先的样式有用户设定。
最低级的优先权由浏览器默认。
6、 属性选择器的权重问题:
// !important ---------> 无穷
// 行间样式-------------> 1000
// id------------------> 100
// class|属性|伪类------> 10
// 标签|伪元素 ---------> 1
// 通配符---------------> 0
权重的进制是256
说一下position都有哪些,并详细的说说他们之间的区别
position:
1、absolute 绝对定位 脱离原来位置进行定位 相对于自身最近的父级进行定位
2、relative 相对定位 保留原来位置进行定位 参照元素自身 用于设置参照物
3、static 默认属性 元素默认定位是static
4、fixed 可视窗口进行定位 网页上应用的广告栏
5、position:sticky是一个新的css3属性,它的表现类似position:relative和position:fixed的合体,
在目标区域在屏幕中可见时,它的行为就像position:relative;
而当页面滚动超出目标区域时,它的表现就像position:fixed,它会固定在目标位置。
淘宝的侧边栏
6、inherit:继承父级的定位
如果position设置成absolute属性该元素的display属性会变成什么
position:absolute和float会隐式的改变display类型,不论之前是什么类型的元素(display:none除外),
只要设置了position:absolute或float,都会让元素以 **display:inline-block** 的方式显示,可以设置长宽,默认宽度并不占满父元素,就算是显示的设置display:inline或display:block,仍然无效。
块级元素行级元素的区别
"block" 块级元素 :占满整行 可以改变宽高
```<div/><from/><address/><hr/><h1/>```
"inline" 行级元素内联元素 :不占满整行 不可以改变宽高
```<a/><br/><em/><span/>```
"inline-block" 行级块元素:可以改变宽高 也不独占整行
```<img/> <input /> ```
可替换元素
可替换元素(replaced element)的展现效果不是由 CSS 来控制的。这些元素是一种外部对象,它们外观的渲染,是独立于 CSS 的。
简单来说,它们的内容不受当前文档的样式的影响。CSS 可以影响可替换元素的位置,但不会影响到可替换元素自身的内容。
典型的可替换元素有 ,还有一些元素仅在特定情况下被作为可替换元素处理,比如
说说怎么去除浮动
(1)为什么要清除浮动?
浮动起来的元素不会脱离文字流 但是会脱离文档流
不脱离文字流:display属性是inline和inline-block 的元素还是可以看见他的 文字本身是inline属性
脱离文档流的意思是 正常元素看不见他了 类似absolute属性
内部改元素的样式display:inline-block;
(2)不清除浮动的效果:
border不能被撑开 背景不能显示 margin设置值不能正确显示
(3)清除浮动的方法:
1.底下添加新的元素 ,应用 clear:both;
2.父级属性:overflow:hidden;
3.可以在外层套一个标签</p> 设置属性 clear:both;
4.添加一个after
xxx:after{
content: '';
clear:both;
display: block;
}
IE67触发haslayout :wrapper{ zoom:1}
"原理":他就是在最后加了一个伪元素 这个元素不是浮动的,他是抗浮动的,所以能看到浮动元素来定位自己的位置
然后父级元素能看到这个伪元素 所以他只是按照这个伪元素的位置来改变自己的宽高
"clear解释":该属性的值指出了不允许有浮动对象的边情况,又对象左边不允许有浮动、右边不允许有浮动、不允许有浮动对象
(4)为什么给父级元素设置overflow属性会去除浮动,具体说说内部机制
触发BFC,计算时会计算浮动元素
BFC的通俗理解:
Block Formatting Context(块级格式化上下文)
如果一个元素符合了成为BFC的条件,该元素成为一个隔离了的独立容器,元素内部元素会垂直的沿着其父元素的边框排列,和外部元素互不影响 。比如浮动元素触发BFC,浮动元素内部的子元素主要受到该浮动元素的影响,而两个浮动元素之间是互不影响的。
BFC的排列:
在BFC中,盒子从顶端开始垂直地 一个接一个地排列,两个盒子之间的垂直的间隙是由他们的margin 值所决定的。在一个BFC中,两个相邻的块级盒子的 垂直外边距会产生折叠。在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来说,则触碰到右边缘)。
BFC的特性
边缘不和浮动元素重叠
不存在collapsing margins问题
第一个特性特别有用,因为元素触发了BFC的话,就不会被float元素覆盖,当子元素全部浮动的时候也能够正确地包含了
第二个margin不会叠加的特性,可以理解为两个处于普通流的盒子,会有margin叠加的问题,是因为他们属于相同的BFC,当他自身创建了一个新的BFC时,这个问题就不存在了
BFC的常见应用
1.通过边缘不和浮动元素重叠的特性,实现两栏结构。
2.清除元素内部浮动
3.解决合并外边距的问题
说说触发bfc的几种方式
1.设置除 float:none 以外的属性值(如:left | right)就会触发BFC
2.设置除 overflow: visible 以外的属性值(如: hidden | auto | scroll)就会触发BFC
3.设置 display属性值为: inline-block | flex | inline-flex | table-cell | table-caption 就会触发BFC
4.设置 position 属性值为:absolute | fixed 就会触发BFC
5.使用 fieldset 元素(可以给表单元素设置环绕边框的html元素)也会触发BFC
html根元素触发BFC
说说常见的将元素垂直水平居中的方法
1.父级定宽高 知道自身宽高
{
position:absolute;
left:50%;
top:50%;
margin-left:-元素宽一半的大小;
margin-top:-元素高一半的大小;
}
2. 父级定宽高 知道自身宽高
{
position: absolute;
top: calc(50% - 50px);
left: calc(50% - 150px);
width: 300px;
height: 100px;
border: 1px solid #000;
}
3.父级定宽高 不知道自身宽高
{
position:absolute;
left:0;
right:0;
top:0;
bottom:0;
margin:auto; 或 margin:0
}
2.父级定宽高 不知道自身宽高
{
position:absolute;
transform:translateX(-50%)translateY (-50%);
}
3.flex 布局 :在父级上
{
position:absolute;
display:flex;
justify-content:center;//水平
aligin-items:center;//竖直
}
4.行内元素水平居中 : text-align: center;
行内元素垂直居中 :height = line-height
盒模型
盒模型
首先我们要区分盒模型和盒子:盒模型有margin部分,而盒子不算margin部分。
1. w3c的标准盒模型,一个盒子的大小是width+padding+border,width是内容区,即width不包含padding和border。
而IE6混杂模式的盒模型,一个盒子的大小是width,即width包含padding和border。
2. css3中就有一个属性可以设置我们使用哪一种盒模型。
box-sizing: border-box IE6混杂模式的盒模型
content-box; 标准模式的盒模型
弹性盒子
这是我认为css3中最重要的一部分。
我们在移动端开发的时候,由于手机的大小都各不相同,所以我们的元素不能定宽,要用弹性盒子来按照百分比分配元素的宽度。
我们给父级的display设置成flex之后,就让父元素变成了一个弹性盒子,里面的子元素都可以使用flex属性了。
这个时候,所有的元素会自动变成一行,因为加上display:flex之后还会默认加上一个flex-wrap:nowrap,即不换行,
这个时候如果子元素的总宽度大于父元素的宽度,就会压缩子元素,让它们可以在父级容器中排成一行。如果改成wrap值,
那么超过容器的宽度之后就会换行了。
//flex属性是一个复合属性,它包括flex-grow、flex-shrink、flex-basis
flex-grow 按比例分配剩余空间。
flex-shrink 设置收缩比例,多出盒子的部分按照比例的大小去掉相应的大小,比例越大,削减的越多,
具体的削减数值有一个复杂的计算公式:
flex-basis 伸缩基准值。该属性设置元素的宽度,如果同时出现了width和该属性,那么会覆盖掉width属性的值。
justify-content:center
align-items:center
这两个属性同时在父级中设置的时候,会让子元素在父级中水平垂直居中,其中justify-content是设置水平方向,align-item是设置垂直方向。
两栏布局类比三栏布局
两栏布局
1.columns width:宽度列
count:列数
2.浮动 左定宽高 浮动 右边设置margin-left
.left{
width:100px;
height:100px;
background-color: red;
float:left;
}
.right{
height:100px;
background-color:green;
margin-left: 100px;
}
3.定位 :左边定宽高 设置定位position absolute left 0 ;
.left{
width:100px;
height:100px;
background-color: red;
position:absolute;
left:0;
}
.right{
height:100px;
background-color:green;
right:0;
}
4.flex 布局 外容器设置display:block;
.wrapper{
display:flex;
}
.left{
width:100px;
height:100px;
background-color: red;
}
.right{
height:100px;
flex-grow:1;
background-color:green;
}
三列布局
有两种实现方式 1.左右两侧的div先用absolute定位,再给中间的div加margin-left和margin-right(值分别是两个div的宽度)
2.用flaot替换上面的absolute就行
.left {
float: left;
width: 100px;
height: 100px;
background-color: orange;
}
.right {
float: right;
width: 100px;
height: 100px;
background-color: red;
}
.mid {
height: 100px;
margin-left: 100px;
margin-right: 100px;
background-color: blue;
}
要注意的是,div.mid记得写在后面,如果写在最前面的话,因为div是block块级元素会独占一行,
这样就会把右侧的div给挤到下一行了。当然我们给.left和.right都加上top:0px;之后,这个问题也就不用考虑了。
3.flex布局
.wrapper{ display:flex}
.left.right{定宽高 背景色}
.middle{flex-grow:1;定高}
middle必须放在中间布局
4.columns属性
原生JS的ofsetwidth求得的宽度包括什么
原生JS的offsetwidth求得的宽度包括什么: content padding border
css(‘width’)求得的宽度包括什么: content padding border
jq的innerWidth求得的宽度包括什么: content padding
line-height 110%和1.1啥区别
一个是相对于父级fontsize,一个是相对自己fontsize的
margin合并和margin塌陷
margin合并问题的现象:并列结构的话 上下两个margin 分别有一个margin-bottom 下边这个元素有一个margintop 这样的画会产生一个重叠取最大的一个margin的值作为他们之间的距离
解决合并外边距的问题:
在CSS当中,相邻的两个盒子(可能是兄弟关系也可能是父子关系)的外边距可以结合成一个单独的外边距。这种合并外边距的方式被称为折叠,并且因而所结合成的外边距称为折叠外边距。按照BFC的定义,只有同属于一个BFC时,两个元素才有可能发生垂直Margin的重叠,这个包括相邻元素,嵌套元素,只要他们之间没有线盒(其实就是非空内容),没有间隙(clearance,设置clear以闭合相关方向的浮动 ),没有padding和border将他们分隔开就会发生margin重叠。解决方式就是使元素不属于同一个BFC。
CSS及浏览器的设计者们希望我们在布局时,如果遇到上下两个并排内容块的安排,最好只设置其中每个块上或下margin的一处即可。
解决方式
解决父子DIV中顶部margin cllapse的问题,需要给父div设置:
1、边框,当然可以设置边框为透明;
2、为父DIV添加padding,或者至少添加padding-top;
3.还可以通过overflow来解决,给父DIV写入: over-flow:hidden;**触发BFC,使之不属于同一个BFC**
说一下 <link/>
和 @import
的区别
<link/>
@import
本质上,这两种方式都是为了加载CSS文件,但还是存在着细微的差别。
[email protected] 机制不同于link,link是加载页面前css加载完毕,@import 是先读取文件再加载
[email protected]是css2.0里的 ie5以上不支持
3.用js控制dom时改变样式,只能用link,@import不是dom能控制的
4.最后一个很有意思,@import url有最大次数的限制,IE6最多引入31次,firefox并没有发现
@import的优点: 多个样式表导入一个样式表中,页面只需要引入一个即可
关于伪元素你了解多少,请说出五个常用的伪元素,那么伪类呢?也请说出五个常用的伪类
"区别":伪元素是相当于添加一个元素 伪类相当于是在元素上添加样式 这俩**都不实际存于在dom树中**
用来格式化文档流之外的东西
伪类则是像真正的类一样发挥着类的作用,没有数量上的限制,只要不是相互排斥的伪类,也可以同时使用在相同的元素上
伪元素:::first-line
:first-letter
:last-letter
:before
:after
伪类: :first-child
:link:
:visitive
:hover
:active
:focus
:lang
HTML5
新增属性scoped
<style scoped>
</style>
scoped 属性是一个布尔属性。
如果使用该属性,则样式仅仅应用到 style 元素的父元素及其子元素。