background-image 不支持 css 过渡,因此修改 --grad-start 或 --grad-end 不会触发动画;根本原因是该属性不可动画,非变量未生效或 bug。

直接改 --grad-start 或 --grad-end 后渐变没变?不是变量没生效,而是 background-image 本身不支持 CSS 过渡,浏览器压根不计算中间帧——你看到的“不动”,是规范行为,不是 bug。
为什么 background-image 中的 var() 改了但不触发重绘
CSS 变量值变了,background-image: linear-gradient(45deg, var(--grad-start), var(--grad-end)) 却没更新,通常是因为:
-
background简写覆盖了变量引用:比如某处写了background: #fff,它会把整个background-image清成none,导致var()失效 - 变量作用域错位:你在
.card里定义了--grad-start,却在button上用var(--grad-start),而button不继承该变量 - 浏览器未识别为可动画属性:即使加了
transition: background-image 0.3s,Safari 16.4 之前、所有 IE/Edge 旧版都静默忽略,DevTools timeline 里根本没动画记录
必须用 background-image 单独声明,不能用 background 简写
很多人把渐变写成 background: linear-gradient(...),再试图用 JS 改 --grad-start,结果毫无反应。这是因为 background 是复合属性,每次赋值都会重置全部子属性,包括 background-image 的来源。
正确做法是拆开写:
button {
background-color: transparent;
background-image: linear-gradient(45deg, var(--grad-start), var(--grad-end));
background-size: 100% 100%;
background-repeat: no-repeat;
}
- 只改
background-image,其他背景子属性(如background-color)保持独立,避免覆盖 - 删掉所有
!important和内联style="background: ...",它们会切断变量链 - 检查 computed style:如果
background-image显示为none或空值,说明有简写冲突或变量未被解析
JS 更新变量后,如何确保渐变立刻重绘
调用 document.documentElement.style.setProperty('--grad-start', '#00f') 后,页面可能延迟一帧才更新——尤其在 Safari 或低端 Android 上。
- 别在 setProperty 后立刻读取
getComputedStyle().getPropertyValue('--grad-start'),它大概率返回旧值;要用requestAnimationFrame包一层再读 - 避免高频修改:比如在
scroll或mousemove里反复 setProperty,会触发大量样式计算,卡顿明显 - 如果需要切换后回调,监听
transitionend事件,但必须过滤:if (e.propertyName === 'background-image'),否则可能误触其他过渡 - 移动端注意:iOS Safari 对
background-image过渡支持仍不稳定,2026 年最新版(Safari 16.4+)才真正可用;旧版建议降级为background-position动画方案
最常被忽略的一点:CSS 变量本身不会“驱动”任何渲染,它只是个占位符。真正决定是否重绘的,是那个被 var() 引用的属性是否属于可动画范畴,以及浏览器是否支持对该属性做插值——background-image 在绝大多数场景下,都不在此列。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











