Custom cursors and cursor hover effects are a great way to impress users on your website, whether you're making an e-commerce website or a portfolio. A good example is a cursor image hover effect, where when the cursor hovers over something it shows an image, here's my way of making it!
Setting up the example
I'll make a short and simple vertical nav with the nav
element for this example. There will be six div
elements in it, and outside the nav is a div with the class of "cursor", that'll be our custom cursor.
<nav>
<div>Lofi</div>
<div>Motivation</div>
<div>Profiles</div>
<div>Goals</div>
<div>Academics</div>
</nav>
<div class="cursor"></div>
Now we add the CSS, that tells the font size, the alignment, and a border on each nav item except the last one.
html, body {
width: 99%;
height: 99%
}
body {
display: flex;
align-items: center;
}
nav {
font-size: 6rem;
display: grid;
}
nav > div:not(div:nth-child(5)) {
border-bottom: solid ;
}
@media (max-width: 480px) {
nav {
font-size: 4.8rem;
}
}
Making and controlling the custom cursor
First, we must remove the visibility of the default cursor by setting the website's (*
) cursor
set to none
. Then we create our custom cursor, which is the cursor div we made before. It'll have a width
and height
of 20px
and its border-radius will be set to 50%
so it becomes a circle. You can add whatever background-color
you'd like for it, I chose black
so it can be easily visible. The most important part is that you set it's position
to fixed
so the cursor always stays in view and pointer-events
to none
so the default actions of how a default cursor would work don't effect the custom one. Finally you set the background-size
to cover
and a scale transition
, these will both be important for the hover effects later on.
* {
cursor: none;
}
.cursor {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: black;
/*Keeps our custom cursor on the user's screen*/
position: fixed;
pointer-events: none;
/*makes sure the background images will sort of fit the cursor*/
background-size: cover;
transition: scale 300ms;
}
Note: I said the visibility of the cursor and not the cursor itself because the computer still does the actions of the cursor such as selecting text even when the cursor isn't shown
Now in Javascript, we make a variable that stores the cursor.
let cursor = document.querySelector(".cursor");
Next, we'll make a function called cursorControl
with an e
parameter that stands for "event". In it we make an X and Y variable that use e.clientX
and e.clientY
to find the coordinates of where the cursor should be based on the movements of the mouse. Then, we place our custom cursor based on our coordinates by setting it's top position to the y
and left position to the x
. Finally, we just call the function in our mousemove
event listener.
function cursorControl(e) {
//tracks the cursors coordinates
let x = e.clientX;
let y = e.clientY;
//places the custom cursor onto the cursor coordinates
cursor.style.top = `${y}px`;
cursor.style.left = `${x}px`;
}
document.addEventListener("mousemove", cursorControl);
There you have it! A custom cursor, now we just need to add the hover effects.
Cursor growth hover effect
Before we go into the Javascript part of things, we need to make a new class called cursorGrow
with a scale
property of 8
. This class will be added to the cursor whenever it hovers over a nav div.
.cursorGrow {
scale: 8;
}
Now, in JS we save all of the nav divs into a variable.
let divs = document.querySelectorAll("div:not(.cursor)");
Furthermore, we make a forEach
method. Where for each div in our nav, when the cursor enters/hovers over them the cursorGrow
CSS class will be added causing the scale of the cursor to go up by 8, but when the cursor leaves the class is removed and the size goes back to normal.
divs.forEach((div) => {
div.addEventListener("mouseenter", function () {
cursor.classList.add("cursorGrow");
});
div.addEventListener("mouseleave", function () {
cursor.classList.remove("cursorGrow");
});
});
Now, because of what we've done so far, the code should create this (make sure to add a transition to the cursor if you hadn't already):
Cursor Image hover effect
Last but not least, we finally add the image hover effect! To add each image, we'll make a CSS classes based on each div an a corresponding image for them.
/*Background image for each div based on their text*/
.lofi {
background-image: url('https://images.unsplash.com/photo-1585477281005-b83d4b47eba4?q=80&w=1887&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D');
}
.motivation {
background-image: url('https://images.unsplash.com/photo-1556711905-4bd1b6603275?q=80&w=1887&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D');
}
.webDev {
background-image: url('https://images.unsplash.com/photo-1498050108023-c5249f4df085?q=80&w=1772&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D');
}
.goals {
background-image: url('https://i.pinimg.com/564x/4d/ee/43/4dee438cb40321df2cb0cfb14a3c7811.jpg');
}
.academics {
background-image: url('https://i.pinimg.com/564x/f8/3d/8b/f83d8b8d17e4315caa647dab88e6addc.jpg');
}
Now we could do this similar to our growth hover effect, where we continue to write mouseenter
and mouseleave
event listeners, but that would be too much code. Instead we could make a loop! But first we need to store the names of each image class in an array and the divs
variable we had before.
let divs = document.querySelectorAll("div:not(.cursor)");
const imageClassNames = ["lofi", "motivation", "webDev", "goals", "academics"];
Now for the loop. How it works is, in the loop there are the mouseenter
and mouseleave
event listeners, and they add and remove classes from the image class array. Whenever a class is added to the div, the div is given the properties of the class, which is the background image of it, but when removed the properties from the class are removed as well, that's how classList.add()
and classList.remove()
work.
To make sure the right class corresponds with the right div, the loop goes from 0 to the length of the array so as long as the order in the divs
array and the imageClassNames
array the correct div and the correct array value always match. So, for example it'll start with the 0th value of the divs
array which is the lofi div, and it'll add the class that's named 0th value of imageClassNames
which is lofi
whenever the mouse enters the div, but removes it when it leaves the div. The loop does it for every value in the image class and divs array, and stops us from writing constant event listeners in our code.
const ImageClassNames = ["lofi", "motivation", "webDev", "goals", "academics"];
for (let i = 0; i < divs.length; i++) {
divs[i].addEventListener("mouseenter", () => {
cursor.classList.add(imageClassNames[i]);
});
divs[i].addEventListener("mouseleave", () => {
cursor.classList.remove(imageClassNames[i]);
});
}
Now, we should finally have our cursor image hover effect!
Conclusion
That's really it! It took me a bit of trial and error to make this cursor hover effect out of my mind, but in the end, it was worth it, which is why I wanted to make a blog about it! I show more of my web dev, game development, and even 3D blender creations on my twitter. Follow for more and have an awesome day/night👋.
Top comments (0)