
本文解决自定义 CSS/JS 光标在页面滚动时脱离鼠标、仅在鼠标移动后才恢复的问题,核心方案是将光标定位方式从 absolute 改为 fixed,并配合使用 clientX/clientY 坐标替代 pageX/pageY。
本文解决自定义 css/js 光标在页面滚动时脱离鼠标、仅在鼠标移动后才恢复的问题,核心方案是将光标定位方式从 `absolute` 改为 `fixed`,并配合使用 `clientx/clienty` 坐标替代 `pagex/pagey`。
当使用 position: absolute 定位自定义光标时,其坐标基准是文档流中的最近定位祖先(通常是
),而 pageX/pageY 返回的是相对于整个文档左上角的坐标(含滚动偏移)。因此,滚动页面时:- 光标仍按 pageX/pageY 计算位置,但 absolute 定位会随文档滚动而“被动移动”;
- 导致视觉上光标漂移、滞后甚至消失——尤其在长页面中尤为明显。
✅ 正确做法是解耦光标与文档滚动:
- CSS 层面:将 .cursor 的 position 改为 fixed,使其始终相对于视口(viewport)定位,不受滚动影响;
- JS 层面:改用 e.clientX 和 e.clientY 获取鼠标在视口内的实时坐标(单位像素,不随滚动变化);
- 同时注意修正偏移量(如 -60px)以实现精准居中。
修改后的关键代码如下:
.cursor {
pointer-events: none;
position: fixed; /* ✅ 关键修改:由 absolute → fixed */
width: 80px;
height: 80px;
background: radial-gradient(circle, #000 0%, #000 3.99%, #fff 4%, #fff 100%);
border-radius: 50%;
mix-blend-mode: exclusion;
transform: translate(-50%, -50%); /* ✅ 更优雅的居中方式(推荐替代 top/left 偏移) */
z-index: 9999;
}
const cursor = document.querySelector('.cursor');
document.addEventListener('mousemove', (e) => {
// ✅ 使用 clientX/clientY + transform 实现精准、高性能定位
cursor.style.left = `${e.clientX}px`;
cursor.style.top = `${e.clientY}px`;
// 或更推荐写法(避免内联样式污染,且性能更优):
// cursor.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`;
});
document.addEventListener('click', (e) => {
cursor.classList.add('click');
setTimeout(() => cursor.classList.remove('click'), 500);
});
⚠️ 注意事项:
- fixed 定位下,top/left 值应直接设为 e.clientX/e.clientY(无需减去偏移),再通过 transform: translate(-50%, -50%) 实现像素级居中,比硬编码 top: ...px; left: ...px 更健壮、可维护;
- 确保 .cursor 元素位于 DOM 树顶层(如 直接子元素),避免被 overflow: hidden 或 transform 等属性意外裁剪;
- 若页面存在 iframe 或第三方组件干扰,可添加 z-index: 9999 强制图层优先级;
- 移动端暂不触发 mousemove,如需兼容触摸设备,需额外监听 touchmove 并做坐标适配。
通过以上调整,自定义光标将真正“粘附”于鼠标指针,在任意滚动深度下均保持即时、稳定、零延迟的跟随效果。











