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)