transition必须写在常态规则中,否则hover移出时无动画;正确写法是基础选择器声明transition,合并transform值,控制缩放范围在1.02–1.05,避免重排与亚像素模糊。
transition 必须写在常态规则里,不能只加在 :hover 中
很多人写了 button:hover { transform: scale(1.04); } 却没动画,是因为漏了关键一步:transition 必须声明在非 hover 的基础选择器中。浏览器靠它预判“哪些属性会变、怎么变”,否则 hover 进入时有动画,移出时直接跳回原状。
正确写法是:
button {
transform: scale(1);
transition: transform 0.2s ease-in-out;
}
button:hover {
transform: scale(1.04);
}
- 别用
transition: all 0.2s—— 它会让 padding、font-size 等意外属性也动起来,可能引发重排或抖动 - 如果按钮本身已有
transform: rotate(2deg),直接写scale(1.04)会覆盖旋转效果;应合并为transform: rotate(2deg) scale(1.04) - Bootstrap 按钮类(如
.btn.btn-primary)权重高,自定义样式要复刻完整类名,比如.btn.btn-primary.custom-scale:hover,否则不生效
缩放值控制在 1.02–1.05 之间,别贪大
超过 scale(1.05) 容易撑破布局,尤其在 Bootstrap 的 .col 或 .btn-group 里,相邻元素会被视觉挤压;更严重的是,Chrome/Firefox 在非整数缩放下可能触发亚像素渲染,文字边缘发虚——这不是 bug,但用户会觉得“糊”。
-
scale(1.03)是多数项目实际采用的平衡点:人眼可感知变化,又不破坏节奏 - 避免搭配
margin-top或top做位移,和scale()叠加可能触发重排;改用transform: translateY(-1px) scale(1.03) - 移动端无
:hover,iOS Safari 默认不触发;如需反馈,得加@media (hover: hover)条件包裹
放大后内容模糊或边框变粗?不是 CSS 写错了
transform: scale() 会等比缩放整个渲染层,包括字体、阴影、边框像素。所以你看到的“模糊”是亚像素渲染机制导致的,而“边框变粗”是因为原始 1px 边框被拉伸成了 1.03px —— 浏览器没法画半像素,只能插值模糊处理。
- 不要退回到
scale(1)或整数缩放,那等于没动;微调transform-origin(比如设为center)有时能缓解 - 边框问题更推荐放弃
border,改用outline+outline-offset模拟,它不受transform影响 - 阴影失真?把
box-shadow换成filter: drop-shadow(),后者是滤镜级渲染,不随缩放拉伸(注意 Safari ≤15.6 兼容性)
想加弹跳或呼吸感?才需要 @keyframes
纯 hover 缩放用 transition + scale() 就够了。只有当你需要非线性节奏(比如先快放再慢回)、多阶段变化(“微缩→放大→回弹”),或联动其他属性(缩放同时改变 opacity 和颜色),才值得上 @keyframes。
例如轻微弹跳:
@keyframes subtleBounce {
0% { transform: scale(1); }
50% { transform: scale(1.06); }
100% { transform: scale(1); }
}
button:hover {
animation: subtleBounce 0.3s ease;
}
-
animation不会自动反向,鼠标移出时不会“弹回去”;如需进出都动,得额外写animation-direction: alternate - 频繁触发
@keyframes动画可能比transition更耗资源,尤其低端安卓机 - 别在
.btn上同时加will-change: transform和@keyframes—— iOS 上容易引发闪烁或滚动卡顿


















