CSS 知识总结

549 阅读3分钟

浏览器渲染原理

构建对象模型

浏览器渲染页面前需要先构建 DOM 和 CSSOM 树。因此,我们需要确保尽快将 HTML 和 CSS 都提供给浏览器。

TL;DR
  字节 → 字符 → 令牌 → 节点 → 对象模型。
  HTML 标记转换成文档对象模型 (DOM);CSS 标记转换成 CSS 对象模型 (CSSOM)。
  DOM 和 CSSOM 是独立的数据结构。
  Chrome DevTools Timeline 让我们可以捕获和检查 DOM 和 CSSOM 的构建和处理开销。

渲染树构建、布局及绘制

CSSOM 树和 DOM 树合并成渲染树,然后用于计算每个可见元素的布局,并输出给绘制流程,将像素渲染到屏幕上。优化上述每一个步骤对实现最佳渲染性能至关重要。

在前面介绍构建对象模型的章节中,我们根据 HTML 和 CSS 输入构建了 DOM 树和 CSSOM 树。 不过,它们都是独立的对象,分别网罗文档不同方面的信息:一个描述内容,另一个则是描述需要对文档应用的样式规则。我们该如何将两者合并,让浏览器在屏幕上渲染像素呢?

TL;DR
DOM 树与 CSSOM 树合并后形成渲染树。
渲染树只包含渲染网页所需的节点。
布局计算每个对象的精确位置和大小。
最后一步是绘制,使用最终渲染树将像素渲染到屏幕上。

下面简要概述了浏览器完成的步骤:

处理 HTML 标记并构建 DOM 树。
处理 CSS 标记并构建 CSSOM 树。
将 DOM 与 CSSOM 合并成一个渲染树 render tree。
根据渲染树来布局,以计算每个节点的几何信息。
将各个节点绘制到屏幕上。

浏览器渲染过程总结

√ 根据HTML构建HTML树 DOM
√ 根据CSS构建CSS书 CSSOM
√ 将DOM和CSSOM合并成一个渲染树 render tree
√ Layout布局(文档流、盒模型、计算大小和位置)
√ Paint绘制(边框颜色、文字颜色、阴影等)
√ Compose合成(根据层叠关系展示画面)

参考来源

渲染性能

渲染树构建、布局及绘制

坚持仅合成器的属性和管理层计数

CSS Triggers

CSS 动画的两种做法(transition 和 animation)

案例1:

demo.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <div id="heart">
    <div class="left"></div>
    <div class="right"></div>
    <div class="bottom"></div>
  </div>
</body>
</html>

demo.css

*{box-sizing: border-box;}
#heart{
  display: inline-block;
  margin: 100px;
  position: relative;
  /* 过渡  持续时间1秒*/
  transition: all 1s;
  
}
/* 鼠标放上去时 触发 */
#heart:hover{
	/* 变形 :缩放1.2倍*/
  transform: scale(1.2);
}

#heart>.left{
  background: red;
  width: 50px;
  height: 50px;
  position: absolute;
  /* 变形:旋转(45°) 在X轴位移(31像素)  */
  transform: rotate(45deg) translateX(31px);
  bottom: 50px;
  left: -50px;
  /* 边框半径 左上 右上 右下 左下 */
  border-radius: 50% 0 0 50%;
}
#heart>.right{
  background: red;
  width: 50px;
  height: 50px;
  position: absolute;
  /* 变形:旋转(45°) 在Y轴位移(31像素)  */
  transform: rotate(45deg) translateY(31px);
  bottom: 50px;
  right: -50px;
  /* 边框半径 左上 右上 右下 左下 */
  border-radius: 50% 50% 0 0;
}
#heart>.bottom{
  background: red;
  width: 50px;
  height: 50px;
  /* 变形 旋转45° */
  transform: rotate(45deg);
}

案例2:

demo.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <div id="heart">
    <div class="left"></div>
    <div class="right"></div>
    <div class="bottom"></div>
  </div>
</body>
</html>

demo.css

* {
  box-sizing: boder-box;
}
#heart {
  /*包裹住里面的div,此处有坑,需注意*/
  
  display: inline-block;
  margin: 100px;
  width: 50px;
  height: 50px;
  position: relative;
  
  /* 动画制作 .5s(持续0.5秒) infinite(永久、无限)alternate-reverse(交替轮流-翻转)*/
  animation: .5s heart infinite alternate-reverse;
}
@keyframes heart {
  0% {
  	/* 变形 缩放1倍 */
    transform: scale(1);
  }
  100% {
  	/* 变形 缩放1.2倍 */
    transform: scale(1.2)
  }
}

.left {
  width: 50px;
  height: 50px;
  background: red;
  position: absolute;
  left: -25px;
  top: -25px;
  /*变形 旋转45° 沿X轴位移5个像素*/
  
  transform: rotate(45deg) translateX(-5px);
  border-radius: 50% 0% 0% 50%;
}
.right {
  width: 50px;
  height: 50px;
  background: red;
  position: absolute;
  right: -25px;
  top: -25px;
  /*变形 旋转45° 沿Y轴位移5个像素*/
  
  transform: rotate(45deg) translateY(-5px);
  border-radius: 50% 50% 0% 0%;
}
.bottom {
  width: 50px;
  height: 50px;
  background: red;
  /*不能写相对定位,否则会发生奇怪的事情,怎么解释?*/
  /*给#heart也加上宽高50px,就恢复正常了*/
  
  position: absolute;
  transform: rotate(45deg);
}

在线案例