@keyframes 中 var(--offset) 不生效是因为其静态编译特性,仅声明时取值一次;需改用 transition: --offset 实现动画,且变量值须带单位(如 calc(var(--offset) * 1px)),并确保 stroke-dasharray 等于路径真实长度。

为什么直接在 @keyframes 里用 var(--offset) 不生效
因为 CSS 动画帧是静态编译的,@keyframes 块里的 stroke-dashoffset: var(--offset) 只会在声明时取一次变量值,后续变量变了,动画不会重触发。这不是 bug,是规范行为——@keyframes 不监听自定义属性变更。
Chrome 110+ / Firefox 112+ 才支持 transition 触发 --offset 重绘
想用变量驱动偏移动画,必须靠 transition 而不是 @keyframes。但老版本浏览器(比如 Safari 16、Edge 112 之前)根本不响应 --offset 的变化,会直接跳到最终态或完全不动。
- ✅ 支持的写法:
transition: --offset 0.6s ease;+ hover/class 切换改变变量值 - ❌ 不支持的写法:
@keyframes draw { to { stroke-dashoffset: var(--offset); } } - ⚠️ 注意:变量值必须带单位(如
calc(var(--offset) * 1px)),否则计算无效
stroke-dashoffset 动画必须配对 stroke-dasharray = 总长
变量控制的是“偏移量”,但前提是路径本身被当作一条连续虚线来处理。如果 stroke-dasharray 没设成路径总长度,比如硬写 stroke-dasharray: 100,而实际路径长是 137.2,那 stroke-dashoffset: 0 时线也不会完整显示,动画终点永远缺一段。
- 必须用 JS 获取真实长度:
const len = path.getTotalLength(); - CSS 中写:
stroke-dasharray: calc(var(--len) * 1px); stroke-dashoffset: calc(var(--offset) * 1px); - 响应式场景下,窗口 resize 后要重新调用
getTotalLength()并更新--len和--offset
伪元素模拟边框时不能直接用 stroke-dashoffset
如果你没用内联 SVG,而是用 ::before + linear-gradient 模拟边框动画,那 stroke-dashoffset 根本不适用——它只作用于 SVG 的 <path></path> 或 <line></line> 元素。这种场景得换思路:
- 用
background-position配合重复渐变实现“移动描边”感 - 或用
mask+background组合,通过mask-position控制显隐区域 - 变量依然可用,但绑定目标变成
background-position-x或mask-position
真正容易被忽略的点是:路径是否闭合、有无圆角、是否含贝塞尔曲线,都会让 getTotalLength() 返回值和人眼感知的“描边节奏”不一致。尤其当 SVG 是从设计稿导出(比如 Figma → SVG),d 属性里藏了大量微小线段或冗余控制点,getTotalLength() 算出来是精确值,但动画过程仍可能卡顿——这不是变量的问题,是路径几何本身导致的映射失真。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











