应使用 transform: scale() 而非 width/height 实现缩放动画,因其不触发 layout、支持硬件加速;transition 必须明确写为 transition: transform 0.2s ease,scale 值宜控制在 1.1~1.3;需注意 inline 元素基线偏移、background-image 不响应 scale、pointer-events: none 失效、cubic-bezier 弹性曲线选择及 svg stroke-width 缩放失真等问题。

transition 用 transform: scale() 而不是 width/height
直接改 width 或 height 触发 layout,动画卡顿且不支持硬件加速;transform: scale() 只影响绘制层,性能好、过渡顺滑。
- 写法必须是
transition: transform 0.2s ease,不能漏掉transform - 别写成
transition: all 0.2s—— 会把 color、opacity 等无关属性也拖进过渡队列,增加渲染负担 - scale 值建议控制在
1.1~1.3之间,超过1.4在小图标上容易糊边或触发字体重排
:hover 伪类里别漏掉 display 或 pointer-events 的副作用
有些图标用 <svg></svg> 或 <i></i> 包裹,如果父容器用了 display: inline-block,悬停时 scale 可能导致文字基线偏移、相邻元素跳动。
- 给图标加
vertical-align: middle或top,稳住行内对齐 - 如果图标是通过
background-image实现的,scale()不生效 —— 得换用transform作用于容器本身 - 用
pointer-events: none的地方要小心:它会让 :hover 失效,缩放就动不了
弹性感靠 cubic-bezier(),不是只调 duration
“弹性”不是指动画变长,而是速度曲线要有回弹趋势。浏览器默认的 ease 是缓入缓出,不够弹;真要模拟物理回弹,得手写贝塞尔值。
- 推荐用
cubic-bezier(0.25, 0.46, 0.45, 0.94)—— 比较接近 iOS 弹性反馈,不突兀 - 避免用
ease-in-out:它两端太慢,中间太快,看着像“飘”,不是“弹” - 移动端要注意:部分旧 Android WebView 对自定义贝塞尔支持弱,可降级为
ease+0.15s更稳妥
SVG 图标缩放时 stroke-width 不随比例变化
SVG 里的 stroke-width 默认是绝对像素值,scale(1.2) 后线条不会变粗,视觉上会显得更细、更轻 —— 和预期“放大变稳重”的感觉相反。
立即学习“前端免费学习笔记(深入)”;
- 加
vector-effect: non-scaling-stroke可以锁死描边粗细,但兼容性差(IE/旧 Safari 不支持) - 更通用的做法:把描边换成
fill形状,或用path模拟粗线,绕过 stroke 缩放问题 - 如果必须用 stroke,可在 :hover 里手动设
stroke-width: 2px(原为 1.5px),数值微调比依赖缩放更可控
真正难的不是写出 scale 动画,而是让不同尺寸、不同来源(font-icon / SVG / PNG)的图标,在缩放时保持视觉重量一致、边缘清晰、不抖动。这点常被当成“样式细节”忽略,结果上线后在 iPad 或高分屏上一眼看出割裂感。










