所有文章 → 文章详情

CSS + JavaScript 自定义网页鼠标指针

这篇文章讨论的是鼠标指针,而不是内存指针(

最近两天一直在折腾网页样式,想给我的主页自定义一个指针样式,而且最好是动态的,于是乎有了这篇记录。

使用 CSS cursor 属性替换

CSS 是支持设置指针格式的,将页面上任意元素的cursor属性设置至目标图标的 url 即可,例如

* {
    cursor: url('arrow.ico'),auto;
}

然而这种方法有一个很明显的缺点,那就是不能设置任何动态指针,也无法给指针实现各种动效。

2025.1.18更:其实是可以通过关键帧实现动态指针的,详见qingzhengQB/ani-cursor.js这个项目。用css cursor属性的优势是操作上无延迟并且性能要求更低,但是如果需要与网页元素互动的指针还是只能用js来实现。

在 HTML 中创造一个指针元素并通过 CSS 和 JavaScript 控制

换一种思路,我们可以通过网页上的一个div来表示鼠标指针,通过 js 和 CSS 来操作它并给他附上动效。

这样做后鼠标指针就成为了网页的一部分,所以我们需要先隐藏掉默认的系统指针:

* {
    cursor: none !important;
}

HTML

现在如果将指针移动到网页上,就会发现它直接消失了,于是我们需要在 HTML 中创建一个div作为我们的新指针。

<div class="mouse"></div>

CSS

在 CSS 中编写指针的样式,我这边写了一个圆作为指针本体。记得将z-index设为999,这样才能让指针显示在所有元素的上方。注意:pointer-events需要设置为none,否则会导制指针本体挡住后方元素。

.mouse {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background-color: #ff9068;
    position: fixed;
    left: 50%;
    top: 50%;
    pointer-events: none;
    z-index: 999;
    transition: background 0.3s, width 0.3s, height 0.3s;
}

我们可以再创建一个lighter类作为指针在链接上方时的样式

.mouse.lighter {
    background-color: #b6ff94;
    width: 10px;
    height: 10px;
}

JavaScript

使用一段 js 让指针元素跟随鼠标移动,并在移动到链接上方时自动添加lighter

var mouse = document.querySelector('.mouse');
document.addEventListener('mousemove', function(e) {
    mouse.style.left = e.pageX + 'px';
    mouse.style.top = e.pageY + 'px';
});

var links = document.querySelectorAll('a');

links.forEach(function(link) {
    link.addEventListener('mouseover', function() {
        mouse.classList.add('lighter');
    });
    link.addEventListener('mouseout', function() {
        mouse.classList.remove('lighter');
    });
});

现在你应该能看到网页上的指针元素在跟随你的鼠标移动了。

动效添加

CSS

只是这样的一个静态指针并不能体现出这个方案的精髓所在。让我们给它加一点动态效果。我决定在这个小圆点外面再添加一个环,并让这个环不断旋转,CSS 代码如下:

.mouse-back {
    position: absolute;
    content: '';
    width: 2em;
    height: 2em;
    background: url(/assets/cursor.svg) no-repeat center center;
    background-size: contain;
    left: -50%;
    top: -50%;
    margin: -0.42em 0 0 -0.42em;
    animation: mouse 3s linear infinite both;
    pointer-events: none;
    z-index: 999;
}

.mouse-back.lighter {
    background-image: url(/assets/cursor-orange.svg);
    width: 2.5em;
    height: 2.5em;
    margin: -0.75em 0 0 -0.75em;
}

JavaScript

小改一下 JavaScript,加入新mouse-back类的控制:

var mouse = document.querySelector('.mouse');
var mouseback = document.querySelector('.mouse-back');
document.addEventListener('mousemove', function(e) {
    mouse.style.left = e.pageX + 'px';
    mouse.style.top = e.pageY + 'px';
    mouseback.style.left = e.pageX + 'px';
    mouseback.style.top = e.pageY + 'px';
});

var links = document.querySelectorAll('a');

links.forEach(function(link) {
    link.addEventListener('mouseover', function() {
        mouse.classList.add('lighter');
        mouseback.classList.add('lighter');
    });
    link.addEventListener('mouseout', function() {
        mouse.classList.remove('lighter');
        mouseback.classList.remove('lighter');
    });
});

我想让外侧的圆环在指针移动的时候不要马上跟随过去,添加一点延迟。这样中间的圆和外侧的圆环不锁死在一起,给网页添加一些动感。

只需在 CSS 的mouse-back类中加入一个transition属性

transition: 100ms;

这样在移动时mouse-back元素就不会马上跟到鼠标的当前位置,而是会有100毫秒的延迟。

效果演示

这样就大功告成了,欢迎来我的网站引导页看看最终的效果:rayann.cn