最稳方案是用 clip-path 配合 transform: scaleY 和 rotate 实现封口动画,避免 height 变化触发重排;需用 animation-direction: alternate 拆分两段实现平滑循环,并通过 @supports 检测降级到 transform 方案。

用 @keyframes + transform 实现封口路径动画
信封封口动画本质是「盖 flap 沿折线闭合」,不能靠纯 CSS 变形(比如 rotate)硬转,因为真实封口是沿一条斜向折线滑动+微旋转。最稳的方式是用 clip-path 配合 transform: translateY 或 scaleY 做遮罩收缩,再叠加轻微 rotate 模拟翻折感。
-
clip-path: polygon()定义初始全开状态(覆盖整个 flap 区域),终点为封口完成态(只留折线附近窄条) - 动画中用
transform: scaleY(1) rotate(0deg)→scaleY(0.05) rotate(-8deg),数值要微调,否则像抽搐 - 别用
height: 100% → 0,会触发重排,卡顿明显;transform和clip-path是合成层属性,更顺
为什么 animation-iteration-count: infinite 会卡顿或跳帧
不停歇的关键不是加 infinite 就完事——真正卡顿的根源是动画终点和起点的视觉/几何不连续。比如 clip-path 从 polygon(0 0, 100% 0, 100% 100%, 0 100%) 收到 polygon(0 0, 100% 0, 95% 90%, 5% 90%),循环时会突然“弹回”全开态。
- 解决办法:把动画拆成两段,用
animation-direction: alternate,让封口→开合→封口自然往复 - 必须设
animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1),原生ease-in-out在折返点太生硬 - 如果用 SVG
<path></path>描边动画,stroke-dasharray和stroke-dashoffset循环时容易因浮点误差错位,建议补上transform: translateZ(0)强制 GPU 加速
兼容性陷阱:Safari 对 clip-path 的 polygon 支持不一致
Safari 15.4+ 才支持 clip-path: polygon() 在 animation 中插值,旧版 Safari 会直接忽略动画,降级成静态封口态。iOS 微信内置浏览器(X5 内核)至今不支持 clip-path 动画。
- 保底方案:用两个重叠的
div,上层是封口 flap 图片,下层是背景信封,靠transform: translateY移动上层模拟闭合 - 检测支持:用
@supports (clip-path: polygon(0 0))套一层,不支持时 fallback 到 transform 方案 - 别在
@keyframes里写百分比单位的clip-path,Safari 会解析失败;统一用px或视口单位(如vw)
性能关键:避免 layout → paint → composite 全链路触发
信封动画常被塞进 position: relative 容器里,结果每次 transform 都触发父容器重绘,尤其页面有滚动时掉帧严重。
立即学习“前端免费学习笔记(深入)”;
- 给动画元素加
will-change: transform, clip-path,但只在动画开始前动态添加,结束就移除,不然长期占用内存 - 确保父容器没设
overflow: hidden且高度固定,否则clip-path可能被意外裁切 - 如果信封图是 PNG,记得用
image-rendering: -webkit-optimize-contrast防止缩放模糊;SVG 更推荐,矢量缩放无损
真正难的不是让 flap 动起来,而是让它在各种屏幕缩放、系统字体设置、甚至深色模式切换时,折线角度和收口位置都不偏移——这意味着所有坐标得用相对单位算,且必须在 JS 里监听 resize 和 orientationchange 做重置。这点多数人一开始根本想不到。










