I'm trying to code a custom cursor that changes its style when hovering over certain elements.
As shown in my code, I tried to define a function that changed the cursor's style when hovering over the div, calling on it using <div id="control" onmouseover="cursorFill()></div>"
. I expected the cursor to change on hover and change back once it was no longer over the div, but instead it changed and did not change back.
I would prefer to do this in vanilla JavaScript if possible (without jQuery or other extensions).
const cursor = document.querySelector('#cursor');
document.addEventListener('mousemove', (e) => {
cursor.style.left = e.pageX + 'px';
cursor.style.top = e.pageY + 'px';
})
function cursorFill() {
document.getElementById("cursor").style.backgroundColor = "#fff";
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
cursor: none;
}
body {
background-color: #000;
align-items: center;
justify-content: center;
display: flex;
}
#cursor {
position: fixed;
width: 20px;
height: 20px;
border-radius: 50%;
border: 5px solid #fff;
background-color: transparent;
transform: translate(-50%, -50%);
pointer-events: none;
mix-blend-mode: difference;
}
#control {
background-color: #fff;
width: 10em;
height: 10em;
margin-top: 50vh;
}
<div id="cursor"></div>
<div id="control" onmouseover="cursorFill()"></div>
The issue is because you only set the background colour when the mouse is over #control
. It needs to be re-set back to its original value when the mouse leaves the element too.
Note in the following example that I removed the inline onmouseover
attribute, as using these is bad practice and should be avoided. Use unobrusive event handlers in your JS instead.
Also note that I amended the logic to add/remove a CSS class from the element. This is to avoid having any CSS logic in your JS code.
Lastly, I changed the event from mouseover
, which fires once for every pixel the mouse hovers over the element, and as such is overkill for this use case, to mouseenter
, which only fires once when the mouse first enters the boundary of the target element.
With those changes made, your code would look something like this:
const cursor = document.querySelector('#cursor');
const control = document.querySelector('#control');
document.addEventListener('mousemove', (e) => {
cursor.style.left = e.pageX + 'px';
cursor.style.top = e.pageY + 'px';
})
control.addEventListener('mouseenter', () => cursor.classList.add('over'));
control.addEventListener('mouseleave', () => cursor.classList.remove('over'));
* {
margin: 0;
padding: 0;
box-sizing: border-box;
cursor: none;
}
body {
background-color: #000;
align-items: center;
justify-content: center;
display: flex;
}
#cursor {
position: fixed;
width: 20px;
height: 20px;
border-radius: 50%;
border: 5px solid #fff;
background-color: transparent;
transform: translate(-50%, -50%);
pointer-events: none;
mix-blend-mode: difference;
}
#cursor.over {
background-color: #FFF;
}
#control {
background-color: #fff;
width: 10em;
height: 10em;
margin-top: 50vh;
}
<div id="cursor"></div>
<div id="control"></div>