font-size 的 transition 无效因单位不一致或含 0 值;应统一单位、避免 0、用 transform: scale() 更可靠,或结合 CSS 变量与 calc() 实现响应式平滑切换。

transition 不能直接作用在 font-size 上
直接写 transition: font-size 0.3s ease; 是无效的——CSS 动画引擎对 font-size 这类离散型属性(尤其涉及单位换算时)默认不触发插值动画,尤其在从 em/rem 切到 px 或 0 时会直接跳变或完全不动。
真正起作用的是让浏览器能计算中间值:必须确保起始和结束状态都使用可插值的数值类型,且单位一致或可映射。
- 用
px、em、rem都可以,但别混用(比如从16px→1.2em) - 避免从
font-size: 0开始过渡(多数浏览器不支持 0→非0 的 font-size 插值) - 如果依赖 JS 动态改字号,确保修改的是内联样式或能被 transition 捕获的 CSS 属性(比如 class 切换)
用 transform: scale() 替代 font-size 更可靠
当目标只是“看起来文字变大变小”,transform: scale() 是更稳定的选择:它走合成层,不触发重排,且所有现代浏览器都能平滑插值。
缺点是缩放会影响布局流(元素本身尺寸没变,但视觉上撑开了),所以适合按钮文字、标题等不牵连周边布局的场景。
立即学习“前端免费学习笔记(深入)”;
- 用
transform: scale(1.2);比font-size: 120%更易控制节奏 - 记得加
transform-origin: center;防止文字偏移 - 如果要保持点击热区不变,需同步调整
padding或用will-change: transform;提前提示渲染引擎
配合 calc() 和 CSS 自定义属性做响应式平滑切换
纯媒体查询切换字号是突兀的,想在断点附近“渐进适应”,得靠 CSS 变量 + calc() + transition 联动。
例如:用视口宽度计算一个比例因子,再乘以基准字号,就能实现随屏幕缩放的连续变化。
html {
--base-size: 16;
--scale-factor: clamp(0.8, (100vw - 320px) / 1280, 1.2);
}
body {
font-size: calc(var(--base-size) * var(--scale-factor) * 1px);
transition: font-size 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}注意:clamp() 的三个参数必须同单位(这里都用无单位数),且 transition 必须写在应用该 font-size 的选择器上,不是 :root。
JS 触发时记得强制 reflow 再改值
用 JS 批量操作样式(比如先删 class 再加 class)时,浏览器可能合并重绘,导致 transition 不触发。
常见现象:文字瞬间变大,没有过渡动画。
- 在修改样式前,读取一次
offsetHeight或getComputedStyle(el).fontSize,强制触发 layout - 或者用
setTimeout(() => { /* 改样式 */ }, 0)把变更推到下一帧 - 更稳妥的做法是用
el.classList.toggle('large-text')配合 CSS 中已定义好的 class 过渡规则,而非直接操作 style
最常被忽略的一点:transition 生效的前提是属性值存在明确的“变化起点”——如果初始状态没设 font-size,或者被其他规则覆盖(比如继承自父级),那第一次过渡大概率失败。检查 computed 样式里的 font-size 是否有确定值,比调 easing 函数重要得多。










