打开网易新闻 查看精彩图片

去年有个数据挺有意思:某头部组件库的动效模块,打包体积占了总大小的23%,而里面70%的代码是在补全浏览器本该原生支持的东西。前端工程师的焦虑,很多时候源于不知道浏览器已经替你做了什么。

CSS(层叠样式表)和SVG(可缩放矢量图形)的动画组合,就是这样一个被严重低估的原生能力。不需要运行时,不需要打包工具的特殊配置,纯标记加样式就能让浏览器自动调用GPU加速。

为什么你的动画总在掉帧

大多数性能问题来自两个操作:布局重算和重绘。当你用JavaScript直接操作元素的宽高、位置时,浏览器被迫重新计算整个页面的几何关系,这叫布局抖动。而修改颜色、阴影这类属性,会触发像素级的重绘。

transform(变换)和opacity(不透明度)是唯二能绕过这两个坑的属性。它们直接交给合成器线程处理,主线程该干嘛干嘛,60帧的流畅度是硬件保证的,不是代码拼出来的。

SVG的特殊之处在于,它的circle、path、rect这些标签本身就是DOM元素。CSS用类选择器就能选中它们,@keyframes(关键帧)的规则完全通用。这意味着你写给div的动画代码,换几个类名就能让图形动起来。

三个实战模式:缩放、旋转、位移

三个实战模式:缩放、旋转、位移

缩放动画的典型场景是入场效果。从0.8倍缩放到正常大小,配合透明度从0到1,能让元素有一种"弹出来"的质感。关键帧的写法很直白:

0% { opacity: 0; transform: scale(0.8); }
50% { opacity: 1; transform: scale(1.05); }
100% { opacity: 1; transform: scale(1); }

注意中间那个1.05倍。故意让元素稍微冲过头再回弹,比线性缩放更有生命力。时间函数用cubic-bezier(三次贝塞尔曲线)控制,上面的数值组合会产生一种弹簧感,不是机械的匀速运动。

旋转和位移的组合可以做出轨道效果。一个圆点绕中心旋转,代码看起来有点绕:

from { transform: rotate(0deg) translateX(60px) rotate(0deg); }
to { transform: rotate(360deg) translateX(60px) rotate(-360deg); }

为什么要写两个rotate?这是为了防止圆点自转。外层的rotate带着整个坐标系转,内层的rotate反向抵消,圆点就能保持正面朝上地画圈。transform-origin(变换原点)设为center,让旋转基准点落在圆心而不是左上角。

交错动画用animation-delay(动画延迟)实现。给一组元素分别设置0秒、0.1秒、0.2秒的延迟,不需要写多个动画定义,CSS的伪类选择器就能搞定。这种波浪式的出现效果,在加载状态和列表渲染里很常见。

零依赖的输出意味着什么

零依赖的输出意味着什么

这套方案的真正价值在工程层面。你输出的只是标记和样式,没有第三方运行时,没有版本冲突,没有tree-shaking(树摇优化)的焦虑。React、Vue、Svelte或者纯HTML,直接粘贴就用。

有个细节很多人没注意:SVG的viewBox(视口框)和CSS的transform是独立坐标系。viewBox负责"画布多大",transform负责"元素怎么动",两者不打架。这让响应式布局下的动画一致性变得简单,不需要像Canvas那样手动处理DPI缩放。

如果你懒得手写关键帧的数学计算,CSSVG这类工具可以可视化编辑时间轴,导出干净的代码。但核心原理不变——浏览器原生的合成管道,比任何JS动画库都更接近硬件。

现在的问题是:你的项目里有多少动画,其实可以删掉依赖、换回原生?