css样式延迟问题
描述: DOM加载快于CSS样式加载导致刷新页面,有1s钟页面没有样式
解决: 给外层包裹元素一个min-width/min-height,会在加载的时候先占一个位置
浏览器渲染CSS的原因
了解浏览器渲染原理是为了解决性能问题。CSS设置会导致重绘和重排,渲染树会造成性能损耗
HTML会被解析成DOM树,CSS文件也会被解析成CSSOM树,DOM树和CSSOM的组合数就是渲染树。
这一过程中,浏览器会确定每个节点的样式到底是什么,并且这一过程是很消耗资源的,因为样式可以自定设置成某个接地那,也可以通过继承获得,这一过程,浏览器得地柜CSSOM树,然后确定具体的元素到底是什么样式。
<div>
<a><span></span></a>
</div>
<style>
span{color:red;}
div > a > span {color: red}
</style>
对于第一种样式的方式,浏览器只需要找到页面中所有的span标签然后设置颜色,但是对于第二种设置样式的方式,浏览器首先需要找到所有的span标签,然后找到span标签上的a标签,最后再去找到div标签,然后给符合这种条件的span设置颜色,这种递归过程很复杂,所以应该尽可能避免写过于具体和模糊的CSS选择器,然后对于HTML来说尽量少的添加无意义标签,保证层级扁平化。
什么情况下阻塞渲染?
渲染的前提是生成渲染树,所以html和css肯定会阻塞渲染,如果想渲染快,就应该降低一开始需要渲染的文件大小,并且扁平化层级,也就是扁平化DOM树,优化选择器。
然后当浏览器解析到script标签时,暂停DOM的渲染,解析完成之后,在从暂停的位置重新渲染,所以说如果想要首屏渲染快,就不应该在首屏加载JS问价,这也是都建议将script标签放在body标签最底部的原因。
并不是说一定需要将script标签放在body标签最底层,也可以加上async或defer属性。
当script标签加上defer属性后,表示JS文件将会并行下载,但是会放在HTML加息完成后顺序执行,所以对于这猴子那个情况可以将script标签放在任意位置。
对于没有任何依赖的JS文件可以加上async属性,表示JS文件下载和解析不会阻塞渲染。
重绘(repaint)和回流(reflow)?
重绘:是当前节点需要更改外观而不会影响布局,比如改变color就叫重绘(针对CSS设置)
重排:是布局或几何属性需要改改称之为重排
重排必定会发生重绘,重绘不一定会引发重排。重排的成本比重绘高得多,改变父节点的子节点很可能会导致父节点一系列重排
以下几个动作可能会导致性能问题:
改变window大小
改变字体
添加或删除样式
文字改变
定位或浮动
盒模型
并且很多人不知道的是重绘和重排其实和Eventloop有关。html文件
减少重排重绘:
使用transform替代top
使用visibility替代display:none 因为前者只会引起重绘,display会造成重排,它改变了布局。
不要把节点的属性值放在一个循环里当成循环里的变量,因为没循环一次都会重新获取正确的值。
不要使用table布局,可能很小的改动会造成整个table的重新布局
动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用requestAnimationFrame
CSS选择符从右往左匹配查找,避免节点层级过多
将频繁的重绘和重排的节点设置为图层,图层能阻止该节点渲染行为影响到其他节点,比如对于vidio标签,浏览器会自动将该接地那变为图层
在不考虑缓存和优化网络协议的前提下,考虑可以通过哪些方式最快的渲染页面,关键渲染路径是什么?
-
从文件的大小考虑
- 从script标签使用上考虑
- 从CSS,HTML的代码书写考虑
- 从需要下载的内容是否需要在首屏使用考虑
CSS的盒模型
理解:元素被一个一个盒子包围着;
盒子分为:
-
块级盒子 block box
- 内联盒子 inline box
控制盒子属于显示哪种类型:
- 控制盒子外部显示类型:display: block display: inline-block
- 控制盒子内部显示类型:display: flex
JS获取盒子宽高
clientHeight : 盒子可视区域的宽高;heigh+padding
offsetHeight: 加上了盒子边框 (一般使用offsetHight/offsetWidth)
console.log( document.getElementById( 'wrap' ).clientHeight );//不包含margin
console.log( document.getElementById( 'wrap' ).offsetHeight );//不包含margin
CSS的盒子模型
盒子模型应用于块级盒子,内联盒子只应用盒子模型的一部分内容。
注: margin 不计入实际大小 —— 当然,它会影响盒子在页面所占空间,但是影响的是盒子外部空间。盒子的范围到边框为止 —— 不会延伸到margin。
盒子模型的分类:
- 盒子模型:width=content-width+padding+border 、 height=content-height-padding+border
- 替代盒模型:width=可见宽度、height=可见高度
- 使用box-sizing: border-box控制
盒子的CSS属性
margin: 两个盒子在一起,外边距会重叠,且取最大的外边距
CSS可继承的属性
font-size,font-family,color,line-height,word-space:增加或减少单词之间的空白字符
等等挺多的;
width不算是继承,给父元素设置50%,子元素并不是父元素的50%,只是默认为父元素的100%
visibility和display:none的区别?
visibility会导致重绘,但是display:none会导致重排,改变了布局,重排的代价比重绘大,且重排肯定会导致重绘,且可能会让父节点产生一系列重排;
在使用上尽量使用visibility代替display:none
CSS项目相关
必填*
.f-required::before {
/* &::before { */
content: '*';
margin-left: -6px;
display: inline-block;
color: #ff5800;
font-size: 14px;
line-height: 1;
/* } */
}
动态调节内容高度
calc(100vh - ?);
~calc(100vh - ?); 不会出现负数