不能,原生 transition 不识别 CSS 自定义属性变化;需将 --x/--y 驱动 background-position 等可动画属性,并用 JS 实时更新变量值,配合 radial-gradient 和精确坐标计算实现平滑光晕效果。

transition 能不能直接过渡 --x 和 --y 这类 CSS 变量?
不能,原生 transition 不识别自定义属性变化,哪怕你用 style.setProperty('--x', newX) 改了值,也不会触发过渡动画。
真正起作用的是「被变量驱动的、浏览器能感知的可动画属性」,比如 transform、background-position、filter: blur()。变量只是中间传值工具,过渡必须落在这些真实属性上。
常见错误:只给 :root 或元素加了 transition: --x 0.2s —— 这行代码完全无效,CSS 解析器会静默忽略它。
光晕效果该用 radial-gradient 还是 box-shadow?
优先用 radial-gradient 配合 background,控制更精细,性能更好;box-shadow 多层叠加容易糊、模糊半径难对齐鼠标位置,且不支持透明度渐变中心点偏移。
立即学习“前端免费学习笔记(深入)”;
核心思路是把光晕做成一个大背景图层,用 background-position 跟随鼠标移动,再靠 background-size 控制扩散范围:
background-image: radial-gradient(circle at var(--x) var(--y), rgba(255,255,255,0.3) 0%, transparent 60%)-
background-position: calc(var(--x) - 50px) calc(var(--y) - 50px)(减去半径是为了让光晕中心对准鼠标) transition: background-position 0.15s ease-out, background-size 0.2s ease
如何让 --x 和 --y 实时响应鼠标移动?
不能只靠 CSS,必须用 JS 抓鼠标位置并写入变量。关键有三点:
- 监听
mousemove事件,用e.clientX/e.clientY获取视口坐标 - 转换为相对于目标容器的坐标(用
getBoundingClientRect()算偏移) - 用
el.style.setProperty('--x', x + 'px')写入,别写进:root——否则全站生效,且无法做局部定位
容易踩的坑:clientX/Y 是全局坐标,如果容器有滚动或缩放,不减去 container.getBoundingClientRect() 的 left/top,光晕就会漂移。
为什么光晕边缘总显得生硬或闪烁?
本质是渲染精度和插值问题。CSS 变量本身是字符串,JS 写入时如果传整数(如 '123'),浏览器可能跳帧;传小数('123.42')并配合 will-change: background-position 能显著改善。
还要注意:
- 避免在
body或大容器上直接设光晕背景,会导致重绘区域过大;建议用伪元素::before层叠在目标元素上 -
radial-gradient的at位置不支持百分比动态插值,必须用像素单位,所以 JS 计算务必带px - 如果容器用了
transform: scale(),鼠标坐标要除以缩放系数,否则光晕会拉伸
最易被忽略的一点:过渡时间别设太长,超过 0.25s 就会明显滞后于鼠标;但低于 0.08s 又看不出缓动效果——0.12–0.18s 是多数场景的甜点区间。


















