监听鼠标移动需用 pagex/pagey 设置 --mouse-x/--mouse-y 变量,配合 calc() 转换单位用于 transform;移动端用 touchmove 兼容;避免重排重绘,合理使用 will-change 和 canvas 优化性能。

监听鼠标移动并实时更新 --mouse-x 和 --mouse-y
核心是用 document.addEventListener('mousemove', ...) 捕获坐标,再通过 document.documentElement.style.setProperty() 写入 CSS 变量。注意必须用 pageX/pageY(不是 clientX/clientY),否则滚动页面时坐标会偏移。
- 计算时减去
scrollX和scrollY可兼容滚动位置,但更简单可靠的做法是直接用pageX/pageY - 避免在事件回调里频繁触发重排,不要操作 DOM 元素的
style.left等属性,只设 CSS 变量 - 若需限制更新频率,可用
requestAnimationFrame节流,而不是setTimeout防抖——动效需要连续性
CSS 中用 calc() 把变量转为像素值并应用到 transform
CSS 变量不能直接参与计算,必须用 calc() 包裹才能用于 translate() 或 background-position。例如 translate(calc(var(--mouse-x) * 1px), calc(var(--mouse-y) * 1px)) 是合法的;而 translate(var(--mouse-x), var(--mouse-y)) 会失效。
-
var(--mouse-x)本身无单位,乘以1px是为了赋予长度语义,CSS 引擎才能解析 - 若想实现「跟随但滞后」效果,可在 JS 中缓存上一帧值做插值,或在 CSS 中用
transition: transform 0.2s ease-out—— 但注意这会导致所有transform变更都带过渡,需谨慎作用域 - 别在
:hover伪类里覆盖这些变量,它和全局监听冲突,优先级不易控制
处理移动端 touch 事件时的兼容写法
移动端没有 mousemove,得监听 touchmove 并取 touches[0]。但要注意:默认行为可能被阻止(如页面缩放),且 pageX/pageY 在部分安卓 WebView 中返回 0。
- 监听
touchmove时加{ passive: false },否则preventDefault()失效 - 优先使用
event.touches[0].pageX,回退到event.changedTouches[0].pageX - PC 和移动端逻辑尽量复用同一套变量名(如统一用
--mouse-x),避免写两套 CSS - 真机调试时发现坐标跳变?大概率是
touch-action: none没加,导致系统默认手势干扰
性能陷阱:避免 layout thrashing 和过度重绘
看似只是设两个变量,但若 CSS 中大量元素都用到了 var(--mouse-x) 并参与 transform,浏览器可能每帧都触发合成层重建,尤其在低配设备上掉帧明显。
- 只对真正需要跟随的元素设置
will-change: transform,别全局加 - 避免在
* { transform: ... }这类通配规则里引用鼠标变量 - 如果动效仅用于装饰(比如粒子、光斑),考虑用
canvas实现,JS 控制坐标比 CSS 变量更可控、更轻量 - Chrome DevTools 的 Rendering 面板打开「Paint flashing」能直观看到哪些区域在疯狂重绘
最易被忽略的一点:CSS 变量是继承的,但 document.documentElement 上设的变量对所有元素都可见——这意味着你写的 var(--mouse-x) 可能在某个深层组件的 ::before 里意外生效,引发难以定位的偏移。作用域意识比语法更重要。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











