关于CSS的艺术审美实现
浏览器渲染原理
先搬上官方背书
可以查看CSS各个属性会触发什么
浏览器的渲染过程
单纯的几个步骤不能很好的复现浏览器这样一个极其复杂的操作系统,下面采用文字与图示相结合的方式再现:
浏览器解析的东西是什么?
答:解析三个东西
一是HTML/SVG/XHTML,HTML字符串描述了一个页面的结构,浏览器会把HTML结构字符串解析转换DOM树形结构。
二是CSS,解析CSS会产生CSS规则树,它和DOM结构比较像。
三是Javascript脚本,等到Javascript 脚本文件加载后, 通过 DOM API 和 CSSOM API 来操作 DOM树和 CSS规则树。
也就是说:
当浏览器拿到一个网页后,首先浏览器会先解析HTML,如果遇到了外链的css,会一下载css,一边解析HTML。
当css下载完成后,会继续解析css,生成css Rules tree,不会影响到HTML的解析。
当遇到
三棵树是什么?
答:
上下两张图中我们需要注意的是:
- 当我们生成 DOM 树和 CSSOM 树以后,就需要将这两棵树组合为渲染树。渲染树只会包括需要显示的节点和这些节点的样式信息,如果某个节点是 display: none 的,那么就不会在渲染树(render tree)中显示。
- 第三棵树是我们后续解析中最主要的依据
- 渲染过程中,如果遇到 < script > 就停止渲染,执行 JS 代码。因为浏览器有GUI渲染线程与JS引擎线程,为了防止渲染出现不可预期的结果,这两个线程是互斥的关系。JavaScript的加载、解析与执行会阻塞DOM的构建,也就是说,在构建DOM时,HTML解析器若遇到了JavaScript,那么它会暂停构建DOM,将控制权移交给JavaScript引擎,等JavaScript引擎运行完毕,浏览器再从中断的地方恢复DOM构建。
- 也就是说,如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件,这也是都建议将 script 标签放在 body 标签底部的原因。当然在当下,并不是说 script 标签必须放在底部,因为你可以给 script 标签添加 defer 或者 async 属性(下文会介绍这两者的区别)。
三棵树都完成之后接下来呢?
答:接下来就是:布局与绘制
- 当浏览器生成渲染树以后,就会根据渲染树来进行布局(也可以叫做回流)。这一阶段浏览器要做的事情是要弄清楚各个节点在页面中的确切位置和大小。通常这一行为也被称为“自动重排”。
- 布局流程的输出是一个“盒模型”,它会精确地捕获每个元素在视口内的确切位置和尺寸,所有相对测量值都将转换为屏幕上的绝对像素。
- 布局完成后,浏览器会立即发出“Paint Setup”和“Paint”事件,将渲染树转换成屏幕上的像素。
如何更新样式?
答:
这几种方式有什么区别?
答:具体来说有三种更新方式
- 第一种方式:全部流程都走一遍
div.remove() 会触发当前消失,其他元素relayout
(具体详细的代码后面再填坑)
- 第二种方式:跳过layout
具体表现就是可能只改变了背景颜色,所以浏览器会直接repaint& composite
(具体详细的代码后面再填坑)
- 第三种方式:跳过layout和paint
具体表现可以是改变transform,这样就只需要composite
注意这个时候必须全屏查看效果,如果在iframe里面看会有一些奇怪的问题
(具体详细的代码后面再填坑)
如何查看CSS属性会触发什么流程?
答:反正最多浏览器就是走这三步,那如果你知道每一个CSS标签会对应触发什么,不就得了,
啊这
我一个一个试吗?(当然不是,用这个)
CSS的动画优化(老生常谈的问题)
答:
- 第一种答案在这里 使用transform来实现动画效果
- 第二种就是JS优化
随便说两个就是:
- 第三种就是CSS优化
举个栗子:
CSS 动画的两种做法(transition 和 animation)
在这里我就放两个版本的做法代码
第一个是animation+彩虹色变化版
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#heart {
margin: 100px;
position: relative;
display: inline-block;
}
.rainbow {
margin-top: 50%;
animation: rainbow 2.5s linear;
animation-iteration-count: infinite;
}
@keyframes rainbow-bg {
100%,
0% {
background-color: rgb(255, 0, 0);
}
8% {
background-color: rgb(255, 127, 0);
}
16% {
background-color: rgb(255, 255, 0);
}
25% {
background-color: rgb(127, 255, 0);
}
33% {
background-color: rgb(0, 255, 0);
}
41% {
background-color: rgb(0, 255, 127);
}
50% {
background-color: rgb(0, 255, 255);
}
58% {
background-color: rgb(0, 127, 255);
}
66% {
background-color: rgb(0, 0, 255);
}
75% {
background-color: rgb(127, 0, 255);
}
83% {
background-color: rgb(255, 0, 255);
}
91% {
background-color: rgb(255, 0, 127);
}
}
@keyframes rainbow {
100%,
0% {
color: rgb(255, 0, 0);
}
8% {
color: rgb(255, 127, 0);
}
16% {
color: rgb(255, 255, 0);
}
25% {
color: rgb(127, 255, 0);
}
33% {
color: rgb(0, 255, 0);
}
41% {
color: rgb(0, 255, 127);
}
50% {
color: rgb(0, 255, 255);
}
58% {
color: rgb(0, 127, 255);
}
66% {
color: rgb(0, 0, 255);
}
75% {
color: rgb(127, 0, 255);
}
83% {
color: rgb(255, 0, 255);
}
91% {
color: rgb(255, 0, 127);
}
}
#heart > .bottom {
width: 50px;
height: 50px;
transform: rotate(45deg);
animation: rainbow-bg 2.5s linear;
animation-iteration-count: infinite;
}
#heart > .left {
width: 50px;
height: 50px;
position: absolute;
bottom: 100%;
right: 100%;
transform: rotate(45deg) translateX(43px);
border-radius: 50%;
animation: rainbow-bg 2.5s linear;
animation-iteration-count: infinite;
}
#heart > .right {
width: 50px;
height: 50px;
position: absolute;
bottom: 100%;
left: 58%;
transform: rotate(45deg) translateY(43px);
border-radius: 50%;
animation: rainbow-bg 2.5s linear;
animation-iteration-count: infinite;
}
</style>
</head>
<body>
<div id="heart">
<div class="left"></div>
<div class="right"></div>
<div class="bottom"></div>
<div class="demo rainbow">HI 完美世界</div>
</div>
</body>
</html>
复制代码
第二种就是简单的transition版本
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#heart {
margin: 100px;
position: relative;
display: inline-block;
transition: all .5s;
}
#heart:hover{
transform: scale(1.5);
}
#heart > .bottom {
width: 50px;
height: 50px;
transform: rotate(45deg);
background-color: cornflowerblue;
}
#heart > .left {
width: 50px;
height: 50px;
position: absolute;
bottom: 100%;
right: 100%;
transform: rotate(45deg) translateX(40px);
border-radius: 50%;
background-color: cornflowerblue;
}
#heart > .right {
width: 50px;
height: 50px;
position: absolute;
bottom: 100%;
left: 100%;
transform: rotate(45deg) translateY(40px);
border-radius: 50%;
background-color: cornflowerblue;
}
</style>
</head>
<body>
<div id="heart">
<div class="left"></div>
<div class="right"></div>
<div class="bottom"></div>
</div>
</body>
</html>
复制代码
自己学习时的一些复盘
- 要养成良好的学习习惯,如果发现好东西就及时去学习,自己查询学习,就比如说在动画上加彩虹变色这个小技巧。(面向谷歌编程~)
- 可以选择自下而上的学习方法,比如说先知道可以做动画的一种方式,然后去了解动画的原理再去了解浏览器的渲染原理,这样很多难懂的术语也会比较容易理解
- 最后,如果发现自己修改一行代码之后突然所有的格式都乱了,也不用担心,慢慢调。问题总有解决的方法,不能心急。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END