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

直接在 @keyframes 里用 var(--offset) 控制 SVG 路径动画,基本无效——它只在 CSS 解析时取一次值,后续变量变,动画不动。
为什么 transition: --offset 是唯一可行路径
浏览器对自定义属性的动画支持,依赖的是 transition 触发重绘,不是 @keyframes 的帧插值。Chrome 110+、Firefox 112+ 才真正支持该行为;Safari 16 和旧版 Edge 仍会跳变或卡死。
- 必须写
transition: --offset 0.4s ease,不能只写transition: stroke-dashoffset -
--offset的值必须带单位(如--offset: 120),使用时补上:stroke-dashoffset: calc(var(--offset) * 1px) - 若 SVG 有
viewBox="0 0 100 100",而实际渲染宽高是 200px × 200px,缩放比为 2,那getTotalLength()返回的是原始坐标系长度,变量需同步乘以缩放比 - 响应式场景下,
resize后必须重新调用path.getTotalLength()并更新--len和--offset
stroke-dasharray 必须等于真实路径长度
描边动画能匀速走完的前提,是虚线模式完全覆盖整条路径。硬编码 stroke-dasharray: 100 而路径真实长度是 137.2,动画永远差一段。
- 用 JS 获取:
const len = path.getTotalLength(); - CSS 中绑定:
stroke-dasharray: calc(var(--len) * 1px); - 初始态要设死:
stroke-dashoffset: calc(var(--len) * 1px);,否则第一帧可能闪动 - 路径不规范会导致
getTotalLength()返回异常值:导出 SVG 时禁用 “简化锚点” 或 “优化路径”,Figma / AI 默认开启这些,容易插入冗余贝塞尔点
颜色也要靠变量驱动,但有前提
stroke 和 fill 支持过渡,但不会自动响应变量变化——必须显式声明 transition: stroke 0.3s, fill 0.3s,且目标值得是确定格式的颜色。
- 禁止用
currentcolor或未定义变量兜底,比如stroke: var(--stroke, currentcolor)在过渡中会失效 - 多色区域必须拆成多个
<path></path>,每个独立绑定变量,如.icon__body { fill: var(--body-color); }、.icon__eye { fill: var(--eye-color); } - 内联 SVG 才能读取父级变量;
<img src="icon.svg">完全隔离样式,currentColor和自定义属性都不可用 - 如果路径原始写了
fill="#000"属性,CSS 的fill: var(--color)不会生效,必须删掉或改为fill="none"
最容易被忽略的初始化细节
加了变量却没动画,往往不是逻辑错,而是漏掉了三处 DOM 级别初始化:
- 没显式设
stroke: currentColor或具体颜色 —— SVG 元素默认无描边 - 没写初始
stroke-dashoffset值 —— 仅靠 hover 切换变量,首帧可能从 0 开始突兀闪动 - 动画没加
animation-fill-mode: forwards或等效的 class 切换策略 —— hover 离开后立刻回弹,进度条“倒流”
真正难调的不是变量本身,而是路径数据和浏览器对 getTotalLength() 的实现差异:同一段 d 属性,在 Chrome 和 Safari 下返回值可能差 0.3px,动画节奏肉眼可察地不一致。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











