1、说说你对 Critical CSS(关键路径 CSS)的理解?如何优化?
答:Critical CSS(关键路径 CSS)就是页面首屏渲染必须的最小化CSS,把它内联在<head>中,确保首屏快速显示,其余CSS异步加载。常见优化手段包括手动提取、构建工具自动生成,以及结合 SSR 提升首屏性能。
- Critical CSS(关键路径 CSS) 指的是页面 首屏渲染必需的最小化 CSS。
- 优化方式就是:把关键
CSS提取出来,内联到<head>,保证首屏尽快渲染;其余非关键CSS异步加载(如通过media、preload、lazy load等)。 - 浏览器渲染页面的关键路径包括:
- 解析
HTML→ 构建DOM树 - 解析
CSS→ 构建CSSOM树 - 合并成
Render Tree → Layout(布局)→ Paint(绘制)
- 解析
其中,外部CSS文件是渲染阻塞资源,必须加载并解析完成才能渲染页面。如果CSS文件很大,或者放在<head>里,容易造成首屏白屏。
- 解决思路:
- 提取页面首屏真正需要的样式(
Critical CSS) - 内联到
<head>,让浏览器能马上渲染首屏 - 其他样式异步加载,不影响首屏
- 提取页面首屏真正需要的样式(
2、谈谈你对CSS动画性能优化的理解。
答:CSS动画本质是让浏览器不断重绘(repaint)或重排(reflow/reflow)元素。动画性能问题主要体现在掉帧(卡顿)、CPU 占用高、移动端发热。
常见导致性能下降的操作:
- 改变布局相关属性(如
width、height、margin、padding) → 会触发reflow。 - 改变影响绘制的属性(如
background-color、border) → 会触发repaint。 - 过度使用
JS控制动画 → 每帧触发DOM操作,也容易掉帧。
性能优化
- 使用
GPU加速- 让动画在
合成层 (composite layer)执行,而不是触发重排。 - 常用属性:
transform(translate、scale、rotate)、opacity - 原理:浏览器会把元素提升为独立图层,动画只改变合成层位置或透明度,不影响布局。
- 让动画在
- 避免触发布局计算的属性动画
- 尽量不要用
width/height/margin/padding做动画 - 改用
transform: scale或translate代替 - 改用
opacity代替visibility切换
- 尽量不要用
- 使用
will-change提前告知浏览器- 告诉浏览器:这个元素接下来会变动,这样浏览器可以提前创建图层。
- 注意:不要给太多元素用,否则会占用大量显存。
- 控制动画帧率
CSS transition/animation默认60fps足够JS动画用requestAnimationFrame而非setInterval
- 减少动画区域和元素数量
- 尽量只动画需要动的元素
- 避免大面积背景色渐变和
box-shadow频繁变化
3、什么是 BFC?它的作用有哪些?怎么创建 BFC?
答:BFC(Block Formatting Context,块级格式化上下文) 是CSS布局中的一块独立渲染区域,这块区域内部的元素布局不会影响外部,外部也不会影响它。可以理解成:BFC 就像一个小的“结界/盒子”,里面的排版规则被独立出来了。
BFC的主要作用:
- 解决浮动元素高度塌陷
- 普通父容器如果只包含浮动元素,高度会塌陷为 0。
- 触发 BFC 后,父容器会包裹浮动子元素。常见写法:
overflow: hidden;
- 避免外边距(margin)重叠
- 垂直方向上两个块级元素的
margin会发生“塌陷”。 - 如果某个元素创建了
BFC,就能避免和外部元素的margin重叠。
- 垂直方向上两个块级元素的
- 阻止元素被浮动元素覆盖
BFC区域会与浮动元素“隔绝”,可以让一个块级盒子避开浮动元素,而不是被它覆盖。
- 独立容器,控制布局
- 在多列布局中,
BFC可以限制内容只在自己的区域内渲染,不会影响旁边的列。
- 在多列布局中,
- 创建
BFC
/* 最常见 */
overflow: hidden;
overflow: auto;
/* 浮动 */
float: left;
float: right;
/* 绝对定位 */
position: absolute;
position: fixed;
/* 弹性/网格布局容器 */
display: flex;
display: inline-flex;
display: grid;
display: inline-grid;
/* 其他 */
display: flow-root; /* 专门用来创建 BFC 的新属性 */
4、伪类和伪元素的区别?请举例说明 :nth-child() 和 :nth-of-type() 的差异。
答:伪类(Pseudo-class):用于选择元素在特定状态下的样式,比如:hover、:nth-child()。伪元素(Pseudo-element):用于创建一个虚拟元素,它本身不在DOM里,比如::before、::after。伪类是“选择已有元素的某种状态”,伪元素是“创建新的抽象元素”。
伪类(:)- 通过已有的
DOM 结构,给某种状态加样式。 - 不会生成新的元素,只是状态选择器。
- 常见:
:hover、:active、:focus、:nth-child(n)。
- 通过已有的
伪元素(::)- 表示一个抽象的“虚拟元素”,可以插入内容。
- 常用于装饰性内容(如小图标、引号、分隔线)。
- 常见:
::before、::after、::first-line、::placeholder。
:nth-child()vs:nth-of-type()的差异:nth-child(2):选择父元素的第二个子元素,不管类型。:nth-of-type(2):选择同类型元素中的第 2 个元素。