不用 border-right 而用 ::before 是因后者可精准定位、支持自定义宽高/背景/动画,避免字体缩放导致的抖动;但需父容器 position: relative,并确保光标动画时长与打字总时长严格对齐。

为什么不用 border-right 而要用 ::before?
因为 border-right 光标在某些字体或缩放比例下会轻微偏移、抖动,且无法独立控制位置和形状;::before 伪元素能精准定位、支持任意宽高/背景/动画,更适合复杂场景(比如非等宽字体、需要垂直居中、或叠加图标光标)。但代价是多一个渲染节点,需确保父容器 position: relative。
::before 光标必须和打字动画严格同步
常见错误是光标提前开始闪、或打完字后还闪几秒——根本原因是动画时长没对齐。假设你用 steps(18, end) 打 18 个字符,每个字符耗时 0.15s,总打字时长就是 2.7s。那么光标动画的 animation-delay 必须设为 2.7s,否则会出现“字没了,光标还在跳”。
-
::before的content: ''+display: inline-block是基础,不能省 - 宽度推荐用
width: 2px或0.05em,避免硬写px导致缩放失真 - 动画用
step-end,不是linear:光标要“硬切换”,不能渐变 - 颜色用
currentColor,自动继承文字色,不用额外维护
怎么让 ::before 光标不干扰文本布局?
伪元素默认会参与行内流,尤其在短文本或单行按钮里容易把文字顶偏。关键控制点:
- 父元素加
line-height: 1.2并保持一致,避免基线浮动 -
::before加vertical-align: middle或baseline,根据字体微调 - 禁用
margin和padding,改用transform: translateY(-50%)垂直居中(配合top: 50%) - 若文本含中文/Emoji,测试
font-family是否统一,否则光标高度可能错位
多行文本里光标只该出现在最后一行
如果打字内容跨多行,::before 光标不能每行都出现——它应该只附着在最后一行末尾。纯 CSS 没法自动识别“最后一行”,所以得手动拆分:
立即学习“前端免费学习笔记(深入)”;
- 把每行文本包进独立
<span></span>,并用animation-delay错开打字起始时间 - 只给最后一行的
<span></span>添加::before光标样式 - 或者 JS 动态计算行高 + 文本高度,插入光标到正确
offsetTop位置(更可靠但增加逻辑)
最易被忽略的是:当用户缩放页面或窗口变窄导致换行时,CSS 无法重算光标位置——这种动态响应必须靠 JS 配合 ResizeObserver 补救。


















