
自定义光标在滚动时消失或错位,是因为其定位依赖于受滚动影响的 pageX/pageY 坐标和 absolute 定位;改为 fixed 定位并使用 clientX/clientY 即可实现始终跟随鼠标、不随滚动偏移的效果。
自定义光标在滚动时消失或错位,是因为其定位依赖于受滚动影响的 `pagex/pagey` 坐标和 `absolute` 定位;改为 `fixed` 定位并使用 `clientx/clienty` 即可实现始终跟随鼠标、不随滚动偏移的效果。
要让自定义光标真正“粘附”于鼠标指针,关键在于两点:坐标系一致性与定位上下文独立性。
首先,CSS 中 .cursor 的 position: absolute 使其相对于最近的 已定位祖先元素(如 body)进行定位。而当页面滚动时,body 的可视区域发生变化,但 absolute 元素的 top/left 值仍基于文档流中的原始位置计算,导致光标视觉上“被拖走”。解决方案是改用 position: fixed——它使元素始终相对于视口(viewport) 定位,滚动不会改变其参考系。
其次,JavaScript 中 e.pageX 和 e.pageY 返回的是相对于整个文档左上角的坐标,会随滚动条位置变化而变化;而 e.clientX 和 e.clientY 返回的是相对于当前视口左上角的坐标,天然与 fixed 定位匹配,无需额外补偿滚动偏移。
✅ 正确实现如下:
.cursor {
pointer-events: none;
position: fixed; /* ← 关键:改为 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%); /* ← 推荐:居中对齐,更精准 */
z-index: 9999;
}
const cursor = document.querySelector('.cursor');
// 使用 clientX/clientY + fixed 定位,天然抗滚动
document.addEventListener('mousemove', (e) => {
cursor.style.left = `${e.clientX}px`;
cursor.style.top = `${e.clientY}px`;
});
document.addEventListener('click', () => {
cursor.classList.add('click');
setTimeout(() => cursor.classList.remove('click'), 500);
});
⚠️ 注意事项:
- transform: translate(-50%, -50%) 配合 left: x; top: y; 可确保光标中心精确对准鼠标点(原代码中手动减去 60px 是为模拟居中,但易出错且不响应尺寸变化);
- 确保 .cursor 元素位于 DOM 顶层(如 直接子元素),避免被其他 fixed 或 transform 元素影响堆叠上下文;
- 若页面存在 scroll-behavior: smooth 或第三方滚动库(如 Locomotive Scroll),需确认其是否劫持原生滚动事件——此时可能需监听自定义滚动事件或使用 requestAnimationFrame 做平滑同步。
通过这一组合调整,光标将彻底脱离文档流束缚,真正实现“所见即所得”的跟随体验。










