删掉 will-change: transform、translatez(0) 和 transform-style: preserve-3d 可使文字立刻变清晰,因模糊源于 gpu 合成层将文字当位图插值处理,而非 transform 本身所致。

直接删掉 will-change: transform、translateZ(0) 和 transform-style: preserve-3d,多数情况下文字立刻变清晰——因为模糊不是 transform 本身造成的,而是它触发的 GPU 合成层把文字当位图处理,插值一开,边缘就糊了。
为什么 Safari 和 Chrome 都会糊,但原因不同
旧版 Safari(≤15.6)对 rotate() 的 GPU 插值极其粗暴,非 90° 倍数角度(比如 rotate(15deg))基本必糊;Chrome 则更依赖图层叠加和亚像素坐标精度——translateX(50%) 在 199px 宽容器里算出 99.5px,浏览器强制舍入后就会糊。两者共性是:文字进了合成层,就失去亚像素渲染能力。
- 打开 Chrome DevTools → Layers 面板,悬停模糊文字,看到红色图层框 → 确认已进 GPU 渲染
- Safari 上糊得特别明显?检查是否同时用了
backface-visibility: hidden或opacity: 0.99—— 这些属性单拎出来就能升层 - 模糊只在动画中出现?大概率是 JS 动态计算的
transform值含小数,比如Math.sin(angle) * 100没四舍五入
真正有效的修复动作(不是加 hack,是删/改/控)
别再试 -webkit-font-smoothing: subpixel-antialiased 或 filter: blur(0),它们在合成层里根本无效,甚至让问题更隐蔽。
- 删掉所有隐式升层属性:
opacity必须是1,filter不能声明(哪怕blur(0)),backface-visibility只在真正需要 3D 翻转时才设,且必须加在变换元素自身 - 用
isolation: isolate包住文字父容器,阻断上级transform或filter的穿透影响 - JS 控制动画时,所有坐标必须取整:
el.style.transform = `translateY(${Math.round(y)}px)`,而不是translateY(${y}px) - 缩放动画优先改
font-size+transition: font-size,不触发图层提升,抗锯齿全程可控
绕不开 transform 时的 Safari 专用底线操作
如果必须用 rotate() 或 scale(),旧版 Safari 要求更苛刻:它对 transform-origin 的小数坐标极度敏感,且 translateZ(0) 在这里不是加速器,是糊化放大器。
-
transform-origin改成整数像素值,比如transform-origin: 100px 100px,避开50% 50%在奇数宽高下算出的 .5px 偏移 - 禁用
translateZ(0)—— 实测在 Safari 15 上,删掉它比加上它文字锐度高约 40% - 必须旋转?改用
rotateZ(15deg)替代rotate(15deg),Safari 对 Z 轴旋转的合成策略略保守,有时能避开最糙路径 - 图标类文字(如按钮里的 “+”)直接改用 SVG:
<g transform="rotate(15)"></g>,SVG 渲染独立于 CSS transform 层
最常被忽略的点是:模糊不是 bug,是 GPU 合成层的默认行为。你调来调去的那些属性,本质是在和浏览器抢控制权——而真正稳的写法,是让文字尽量不动,或只动它该动的部分。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











