纯 CSS 无法实现 radial-gradient 真正跟随鼠标移动,因 var(--x) 在 radial-gradient 函数内不被解析,浏览器直接忽略;必须用 JS 动态计算容器内百分比坐标并设置 style.backgroundImage。

纯 CSS 无法让 radial-gradient 真正跟随鼠标移动——var(--x) 在 radial-gradient(circle at ...) 中不会被解析为有效坐标,浏览器直接忽略整个声明。必须靠 JS 实时更新变量,并用内联样式或 background-image 字符串拼接来绕过限制。
为什么 radial-gradient(circle at var(--x) var(--y)) 不生效
CSS 函数体内不执行变量替换,var() 只在属性值层面起作用(如 background-position: var(--x)),但 radial-gradient() 是函数调用,其参数不参与 CSS 自定义属性解析流程。即使你写了 --x: 100px,at var(--x) var(--y) 仍被当作无效语法丢弃。
- 现象:光斑始终不出现,或默认回退到
at 0 0(左上角) - 验证方式:打开 DevTools → Computed → 查看
background-image是否为空或 fallback 到初始值 - 替代方案只有两个:用 JS 动态写入
element.style.backgroundImage,或改用background-position+ 固定渐变中心(模拟跟随感)
最稳的 JS + CSS 变量协作写法
核心是把坐标算成容器内百分比,再注入到 background-image 字符串中,避免单位混用和解析失败。
- 监听
mousemove和touchmove,移动端必须处理e.touches[0] - 用
getBoundingClientRect()获取容器位置,计算相对坐标:const x = (e.clientX - rect.left) / rect.width * 100 - 边界保护:
x = Math.max(0, Math.min(x, 100)),防止超出后光斑消失 - 动态设置:
el.style.backgroundImage = `radial-gradient(circle at ${x}% ${y}%, rgba(255,255,255,0.2) 0%, transparent 70%)` - 别用
pageX/pageY:滚动后坐标偏移,光斑“掉出”可视区
mask-image 方案里 --x/--y 总卡在左上角
这不是变量没更新,而是遮罩三要素缺失。CSS 变量能传进去,但没配套规则,浏览器就不渲染光斑。
立即学习“前端免费学习笔记(深入)”;
- 必须显式声明:
mask-image: radial-gradient(circle, #000, transparent 80%) - 必须设尺寸:
mask-size: 300px 300px(默认铺满容器,光斑不可见) - 必须禁重复:
mask-repeat: no-repeat(否则多个光斑叠在一起) - 必须设定位:
mask-position: var(--x) var(--y),且--x/--y需提前在:root或元素上初始化,例如:root { --x: 50%; --y: 50%; } - 单位要统一:如果用百分比,就全用
%;如果用像素,JS 更新时就得带px,不能一半%一半px
真正难的不是写 JS 更新变量,而是坐标是否相对于容器、单位是否一致、遮罩是否被其他 background 属性覆盖——这三个点漏一个,光斑就动不了。别信“纯 CSS 跟随”,那只是 hover 假象或固定偏移。


















