Skip to main content

CSS 动画

前端实现动画主要有三种方案:JS 动画(如 requestAnimationFrame)、CSS3 过渡(transition)和 CSS3 关键帧动画(animation)。CSS 动画的面试核心是开启硬件加速 (GPU) 以避免主线程阻塞。

CSS 动画两大核心属性

1. transition (过渡动画)

它用于在元素状态发生变化时(如 :hover,或被 JS 添加了某个类名)平滑地改变 CSS 的属性值。

  • 触发条件:必须要有外部事件或交互触发。
  • 特点:一次性,不能循环,只能定义开始和结束两个状态。
  • 核心语法transition: property duration timing-function delay;
    .box {
    width: 100px;
    transition: width 0.5s ease-in-out;
    }
    .box:hover {
    width: 200px; /* 鼠标放上去时,宽度会花 0.5s 慢慢变长 */
    }

2. animation (关键帧动画)

它用于实现更复杂、不需要外部触发就能自动执行的连续动画。

  • 触发条件:页面加载完毕即可自动运行。

  • 特点:可以定义多个阶段(0% - 100%),可以控制循环次数、方向、甚至暂停状态。

  • 核心语法:首先定义 @keyframes,然后通过 animation 属性调用它。

    @keyframes spin {
    0% {
    transform: rotate(0deg);
    }
    100% {
    transform: rotate(360deg);
    }
    }

    .loader {
    animation: spin 2s linear infinite; /* 无限循环转动 */
    }

核心面试题:什么是“硬件加速”?如何用 CSS 开启?

在聊动画时,面试官一定会顺藤摸瓜问你:“如果在低端手机上 CSS 动画很卡,你会怎么优化?”

问题本质:如果你用 widthheighttopleft 这种布局属性做动画,每一帧的变化都会导致浏览器重新计算布局(引发剧烈的回流 Reflow),由 CPU 在主线程去一帧帧地画,肯定会卡死。

解决方案:开启 GPU 硬件加速 现代浏览器将渲染过程分为了“主线程”和“合成线程(Compositor Thread)”。 如果你使用 transformopacity 这两个属性来做动画,浏览器会极其聪明地将这个元素提升为一个独立的合成层 (Compositor Layer)。 在这个层里,所有的位移、缩放、透明度变化,都会直接交由 GPU 去处理,完全跳过重排和重绘阶段,并且不占用 JS 主线程,性能直接拉满!

如何强制开启硬件加速? (Hack 技巧) 有时候就算没做动画,为了解决页面滚动时的某些渲染瓶颈,前端老鸟会写出下面这种“看起来毫无意义”的代码,目的就是为了“骗”浏览器把这个元素强行提层交给 GPU:

.accelerate {
/* 以下写法都可以强制触发 3D 硬件加速 */
transform: translateZ(0);
transform: translate3d(0, 0, 0);
/* 现代浏览器推荐的正规写法:告诉浏览器我马上要变了,请提前准备 GPU */
will-change: transform;
}

注意坑点:硬件加速不能滥用!GPU 的显存非常宝贵(且移动端往往和 CPU 共享内存),如果你给页面上几百个元素都加了 transform: translateZ(0),会导致浏览器内存飙升,最终闪退崩溃(Crash)。