HTML/CSS
HTML&CSS篇(第一个版本该篇预计总结常见问题20个左右),HTML&CSS不少问题都能体现应届生对于前端基础的掌握程度,是应届生求职时不可忽视的重要一环
Last updated
HTML&CSS篇(第一个版本该篇预计总结常见问题20个左右),HTML&CSS不少问题都能体现应届生对于前端基础的掌握程度,是应届生求职时不可忽视的重要一环
Last updated
大致过程:
HTML解析构建DOM->CSS解析构建CSSOM树->根据DOM树和CSSOM树构建render树->根据render树进行布局渲染render layer->根据计算的布局信息进行绘制
不同浏览器的内核不同,所以渲染过程其中有部分细节有不一样,以webkit主流程为例:
一篇很棒的文章(需科学上网):How Browser Work
编者有话说:浏览器解析渲染页面过程是一个复杂的过程,其中有不少的细节和规则,如果把上面分享的文章翻译成译文,至少有3~5页PDF左右,所以这里只能总结大致过程(作为面试回答【很可能让回答的尽可能详细】了解来说已经足够,更深入的了解可以好好读下上面那篇文章)
较详细过程:
HTML解析构建DOM树:其中HTML Parser就起到了将HTML标记解析成DOM Tree的作用,HTML Parser将文本的HTML文档,提炼出关键信息,嵌套层级的树形结构,便于计算拓展;这其中也有很多的规则和操作,比如容错机制,识别特殊标签<br></br>
等
CSS解析构建CSSOM树:CSS Parser将很多个CSS文件中的样式合并解析出具有树形结构Style Rules,也叫做CSSOM。
※其中还有一个细节是浏览器解析文档:当遇到
<script>
标签的时候会停止解析文档,立即解析脚本,将脚本中改变DOM和CSS的地方分别解析出来,追加到DOM Tree和CSSOM上
根据DOM树和CSSOM树构建Render树:Render Tree的构建其实就是DOM Tree和CSSOM Attach的过程,在webkit中,解析样式和创建呈现器的过程称为"附加",每个DOM节点都有一个"attach"方法,Render Tree其实就相当于一个计算好样式,与HTML对应的Tree
根据Render树进行布局渲染render layer:创建渲染树后,Layout根据根据渲染树中渲染对象的信息,计算好每一个渲染对象的位置和尺寸,将其放在浏览器窗口的正确位置,某些时候会在文档布局完成之后进行DOM修改,重新布局的过程就称为回流
※其中计算(样式计算)一个复杂的过程,因为DOM中的一个元素可以对应样式表中的多个元素,Firefox采用了规则树和样式上下文树来简化样式计算,规则树包含了所有已知规则的匹配路径,样式上下文包含端值,webkit也有样式对象,但它们不保存在类似上下文树这样的结构中,只是由DOM节点指向此类对象的相关样式
根据计算的布局信息进行绘制:绘制阶段则会遍历呈现树,并调用呈现器的paint方法,将呈现器的内容显示在屏幕上,绘制的顺序其实就是元素进入堆栈样式上下文的顺序,例如,块呈现器的堆栈顺序如下:1.背景颜色,2.背景图片,3.边框,4.子代,5.轮廓
区别:
回流指当前窗口发生改变,发生滚动操作,或者元素的位置大小相关属性被更新时会触发布局过程,发生在render树,比如元素的几何尺寸变化,就需要重新验证并计算Render Tree
重绘指当前视觉样式属性被更新时触发的绘制过程,发生在渲染层render layer
所以相比之下,回流的成本要比重绘高得多
减少回流重绘次数的方法:
1)避免一条一条的修改DOM样式,而是修改className或者style.classText
2)对元素进行一个复杂的操作,可以先隐藏它,操作完成后在显示
3)在需要经常获取那些引起浏览器回流的属性值时,要缓存到变量中
4)不使用table布局,一个小的改动可能就会引起整个table重新布局
5)在内存中多次操作节点,完成后在添加到文档中
页面性能优化有一条,用transform代替top,left来实现动画。那么transform的优势在哪里?如何开启GPU加速渲染?开启GPU硬件加速可能会触发的问题,如何解决?
首先相比定位的top&left来说,transform不会引起整个页面的回流和重绘。其次我们可以通过transform开启GPU硬件加速,提高渲染速度,但相应的transform也会占用更多的内存。
可能会导致浏览器频繁闪烁或者抖动,解决方案:
首先需要了解的是,移动端在touch上一共有4个事件,
执行顺序为touchstart -> touchmove -> touchend -> touchcancel
当用户点击屏幕时,会触发touch和click事件,touch事件会优先处理,touch事件经过捕获,目标,冒泡一系列流程处理完成之后,才会触发click,所有我们经常会谈到移动端点击事件300ms延迟的问题
移动端点击事件300ms问题,常见的解决方案:
阻止用户双击缩放,并限制视口大小
设置csstouch-action
用于指定某个给定的区域是否允许用户操作,以及如何相应用户操作
fastclick.js来解决,其原理是在检测到touchend事件的时候,会通过自定义事件立即触发模拟一个click事件,并在300ms之后把真正的click事件阻止掉
点透现象:
发生条件:①按钮A和按钮B不是后代继承关系,②A发生touch,A touch后立即消失,B绑定click,③A z-index大于B,即 A 显示在 B 浮层之上
发生原因:当点击屏幕时,系统生成touch和click两个事件,touch先执行,touch执行完之后A消失,然后要执行click的时候,就会发现用户点击的是B,所以就执行了B的click
解决方法:①阻止默认事件,在touch的某个时间段执行event.preventDefault,去取消系统生成的click事件,一半在 touchend 中执行。②要消失的元素延迟300ms后在消失
Doctype是一种DTD文档定义类型,必须声明在HTML文档的第一行,用来规范文档使用哪种方式解析HTML,三种模式分别是怪异模式,标准模式,近乎模式(IE8的一种近乎于前两者之间的一种模式);标准模式按照HTML和CSS定义渲染,怪异模式会模拟更旧的浏览器行为
标准盒模型和IE怪异盒模型,标准盒模型下:盒子总宽度/高度=width/height+padding+border+margin
怪异盒模型,IE5.X 和 6 在怪异模式中使用自己的非标准模型,盒子的总宽度和高度是包含内边距padding和边框border宽度在内的:盒子总宽度/高度=width/height + margin = width/height + margin;
boxsizing属性content-box使用标准盒模型的计算方式,border-box则使用怪异盒模型的计算方式
首先,margin塌陷是相对于父子级关系的两个元素,而margin合并是相对两个兄弟级关系的两个元素
两个兄弟级关系的元素,垂直方向上的margin,其外边距会发生重叠现象,两者两个的外边距取的是两个所设置margin的最大值,就是所说的margin合并问题
两个父子级关系的元素,垂直方向上的margin会粘合在一起,外层和模型的margin-top取两个元素中margin-top的最大值,发生margin塌陷的内层元素相对于整个文档移动
解决方案:两者都可以通过触发BFC来解决
首先需要知道文档流分为定位流,浮动流和普通流三种,而普通流则是BFC中的FC(格式化上下文),它是页面的一块渲染区域,有一套渲染规则,决定了子元素如何布局,以及和其他元素之间的关系和作用,常见的FC有BFC,IFC,还有GFC和FFC
BFC块级格式化上下文,IFC行级格式化上下文,
哪些元素会触发BFC:
根元素
float的属性不为none
position属性为absolute或fixed
display为inline-block,table-cell,table-caption,flex
overflow不为visible
absolute会使元素位置与文档流无关,不占据空间,absolute 定位的元素和其他元素重叠
relative相对定位时,无论元素是否移动,仍然占据原来的空间
sticky是2017年浏览器才开始支持,会产生动态效果,类似relative和fixed的结合,一个实例是"动态固定",生效前提是必须搭配top,left,bottom,right
一起使用,不能省略,否则等同于relative
定位,不产生"动态固定"的效果
使用Flexbox
百分比布局结合媒体查询
使用rem
rem转换像素大小(根元素的大小乘以rem值),取决与页面根元素的字体大小,即HTML元素的字体大小
em转换像素大小(em值乘以使用em单位的元素的字体大小),比如一个div的字体大小为16px,那么10em就是180px(或者接近它)
rem平时怎么做的转换:为了方便计算,时常将html的字体大小设置为62.5%,那么12px就会是1.2rem
① flex实现水平垂直居中
② 进行垂直水平居中(利用transform中translate偏移的百分比值是相对于自身大小的特性)
① 绝对定位+margin:auto
② 使用绝对定位与负边距
三栏布局:两侧定宽中间自适应,在开发中很常见的布局方式,主要有下面六种实现方式:
最简单的方式就是通过float实现
利用绝对定位
利用BFC规则
圣杯布局(通过margin负值调整)
双飞翼布局(和双飞翼布局类似,只是处理中间栏被遮挡的方式不同:双飞翼布局在中间栏内部加一个div,设置其margin来避开遮挡)
利用flex布局 👇 Q14
flex意为弹性布局,有两大概念,一是容器(container),二是项目(item),两者都有各自的六个常用属性
用在容器上的六个属性:
flex-direction
主轴的方向,
flex-wrap
一条轴线装满,如何换行,
flex-flow
是前两者的简写,
justify-content
项目在主轴上的对齐方式
align-items
在交叉轴上如何对齐
align-content
多跟轴线的对齐方式
用在项目上的六个属性:
order
排序顺序,默认为0,越小越靠前
flex-grow
项目的放大比例,默认为0,不放大
flex-shrink
项目的缩小比例,默认为1,空间不足该项目会缩小
flex-basis
项目占据主轴空间大小
flex
是上面放大,缩小,大小三者的简写,默认为0 1 auto
align-self
允许单个项目有不同于其他的对齐方式
清除浮动主要是为了解决父元素因为子元素浮动内部高度为0的问题
额外标签,即在最后一个浮动标签后加一个空div,给其设置clear:both
,缺点是增加无意义标签,语义化差
给父级元素添加overflow:不为visible
通过触发BFC的方式清除浮动
使用after伪元素,缺点是IE6-7不支持伪元素,zoom:1触发hasLayout
使用before和after双伪元素清除浮动
css sprits又名雪碧图,也叫css精灵,开发人员会将很多小图标合并在一起之后的图片成为雪碧图,使用时通过background-image、background-position和background-size属性,将对应的小图标添加元素中
优点是:
减少加载多张图片的HTTP请求数
可以提前加载资源
缺点是:
维护成本较高,需要改动这张合并的图片
加载优势在http2之后不复存在,http2采用多路复用,多张图片也可以重复使用一个连接
cookie,localstorage,sessionstorage,IndexedDB
(追问)这些方式的区别是什么,分别介绍一下:
cookie:HTML5标准前本地存储主要方式,请求头带着数据,缺点是大小只有4k左右,并且自动请求头加入cookie浪费流量,每个domain限制20个cookie,使用起来也麻烦需要自行封装
localstorage:HTML5标准后加入,以键值对(key-value)方式存储,永久存储,永不失效,除非手动删除,IE8+支持,每个域名限制5M
sessionstorage:和localstorage操作方法一样,区别在于sessionstorage在关闭页面后即被清空,刷新不会清空,但是不能在所有同源窗口中共享,是会话级别的存储方式
IndexedDB:被纳入HTML5标准的数据库存储方案,它是一个NoSql数据库,用键值对进行存储,可以快速读取操作,适合web场景和JavaScript操作