用伪元素 ::after 模拟下划线,设 position: relative 于容器,::after 含 content: ""、display: block、height: 2px、bottom: -2px,初始 transform: scalex(0),悬停 transition: transform 0.3s ease 至 scalex(1),并设 transform-origin: left bottom。

用 transform: scaleX() 实现下划线延伸动画
直接用 text-decoration 无法单独控制下划线长度或做缩放动画,必须用伪元素模拟下划线。核心是:给文字加 ::after,初始 scaleX(0),悬停时过渡到 scaleX(1)。
- 必须设
position: relative在文字容器上,否则伪元素定位会错乱 -
::after要设content: ""、display: block、height: 2px(或你想要的粗细) - 用
bottom: -2px控制下划线离文字的距离,数值需配合字体大小微调 - 过渡要写在伪元素上,不是父元素:
transition: transform 0.3s ease
为什么不能只靠 width + overflow 模拟
有人试过用子 span 包文字、再用另一个 span 做下划线并设 width: 0 → width: 100% 过渡,但问题明显:
- 文字换行时,下划线会断开或错位,
scaleX在 inline 元素上天然跟随文本流 -
width动画在 flex 或 grid 容器中容易受父级约束干扰,而transform不触发重排,性能更稳 - 部分浏览器对
width的小数像素渲染不一致,scaleX插值更平滑
transition 写在哪?常见漏掉的三处
动画失效往往不是逻辑错,而是过渡属性没挂对地方:
- 伪元素的
transform必须配transition,写在父元素上无效 - 如果用了
will-change: transform提升图层,记得只在悬停态加,避免常驻消耗 GPU - 别忘了设
transform-origin: left bottom(默认是中心),否则缩放会从中间向两边展开,不是从左向右延伸
兼容性与字体适配细节
这个效果在 Chrome/Firefox/Safari(≥15.4)和 Edge ≥100 都没问题,但有两个实际坑点:
- 中文字体下划线位置偏高(尤其思源黑体、PingFang),需要手动调
bottom,比如bottom: -4px - 如果文字用了
line-height> 1,伪元素的bottom值得按比例放大,否则悬停时下划线会“浮起来” - 移动端 Safari 对
transform+inline元素的渲染偶有闪烁,加-webkit-backface-visibility: hidden可缓解
真正麻烦的是多语言混排场景——英文单词间空格、中文无空格、数字连写,会导致伪元素宽度计算偏差。这时候得放弃纯 CSS,改用 JS 测量 getBoundingClientRect() 动态设 width,scaleX 就不管用了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











