In this blog post we will recreate windows 10 start menu's button hover effects,
you can try the final result on codepen -
1. Create a card with basic stylings.
First of all you need a basic card with some stylings -
<div class="card">
<h1>Hi dev.to!</h1>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nemo ut</p>
</div>
.card {
border-radius: 10px;
padding: 20px;
width: 210px;
height: 150px;
background: rgb(26,26,26);
}
and I am also gonna add some styling to <body>
to position the card in the center, add a better font and change background & text color -
body {
margin: 0;
background: black;
font-family: Verdana, sans-serif;
color: white;
display: inline-flex;
flex-direction: row;
justify-content: center;
align-items: center;
align-content: center;
min-height: 100vh;
width: 100%;
gap: 8px;
flex-wrap: wrap;
}
Now the page should like this -
2. Creating a border
Now we need to create a border which will glow when the mouse comes near it.
But we cant just use css border
property for this. Imagine if that property didn't existed? How would you make a border then.
You would add the element inside a
<div>
with abackground
.
so we will rename the .card
class to .inner
and create a new class .card
-
.card {
background: red; /* border color */
padding : 3px; /* border width */
border-radius: 12px;
}
and wrap it around the card -
<div class="card">
<div class="inner">
<h1>Hi dev.to!</h1>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nemo ut</p>
</div>
</div>
And now you have a border -
we are going to keep the border color red
for now.
3. Adding Light & Glow Effect
Now we we will create a new element and give it a class .blob
-
<div class="card">
<div class="inner">
<h1>Hi dev.to!</h1>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nemo ut</p>
</div>
<div class="blob"></div>
</div>
and the element will be positioned absolute
-
.blob {
filter: blur(40px);
position: absolute;
z-index: -1; /* to keep it at below everything else */
top: 0; /* to align it at top */
left: 0; /* to align it at left */
width: 250px;
height: 250px;
border-radius: 50%; /* to make it circular */
background: rgb(255, 255, 255, 0.5);
}
Now the blob should appear on top-left of the window -
but we wanted it to be on the top-left of the card.
The reason it went on the top-left of the window is because the absolute positioned element needs a non-static position element to position themselves along.
Since it didn't find any non-static elements it position itself along the <body>
.
so to fix it add a position: relative;
to the .card
class -
.card {
background: red;
padding : 3px;
border-radius: 12px;
position: relative;
}
Now it should position itself along the .card
.
But now the the glow is escaping out of the card, which we don't want.
You might think, we also want other cards near it to glow. But we only want the border of surroundings to glow, and now the card is just spreading the light everywhere. Instead every card will have their own light which will go towards the mouse and glow their borders.
So, we will add overflow: hidden;
to .card
class to stop it from spreading out, and we will also change the border color to
background: rgb(128 128 128 / 0.2);
, so that we can actually see the glow
.card {
background: rgb(128 128 128 / 0.2);
padding : 3px;
border-radius: 12px;
position: relative;
overflow: hidden;
}
Now you should be able to see the glow -
4. Making the blob follow the mouse.
Now we will start writing some javascript!
first of all you need another element with a class .fakeblob
-
<div class="card">
<div class="inner">
<h1>Hi dev.to!</h1>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nemo ut</p>
</div>
<div class="blob"></div>
<div class="fakeblob"></div>
</div>
.fakeblob {
display: hidden;
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 200px;
height: 200px;
border-radius: 50%;
}
we just need this because we need the original position of the blob, and thats why its display: hidden;
.
But why can't we save the original in a JS variable, and use it later on? We can't because the blob's original position might change like on scroll and zoom in/out, so we used a fakeblob.
Now the Javascript part!
First of all we will fetch all our card elements and save it in a variable -
const allCards = document.querySelectorAll(".card");
Then we will add add an eventListener, which will listen to mouse movement, inside it we will loop through all of the cards and fetch its .blob
and .fakeblob
childrens -
window.addEventListener("mousemove", (ev) => {
allCards.forEach((e) => {
const blob = e.querySelector(".blob");
const fblob = e.querySelector(".fakeblob");
});
});
then we will getBoundingClientRect()
of the fakeblob
which will return an object providing information about the size of an element and its position relative to the viewport -
allCards.forEach((e) => {
const blob = e.querySelector(".blob");
const fblob = e.querySelector(".fakeblob");
const rec = fblob.getBoundingClientRect();
});
now we will animate the blob
using the web animation api -
blob.animate(
[{
transform: `translate(${ev.clientX - rec.left - (rec.width / 2)}px,${ev.clientY - rec.top - (rec.height / 2)}px)`,
}],
{
duration: 300,
fill: "forwards",
}
);
here we are animating it for the duration - 300ms
and fill - forwards
means that the element will keep the styles of the last keyframe.
and in the animation we are translating it by the difference between mouse position and fake blob position.
And we also subtracting it by half of its height in y axis and half of width in x axis. The reason for this is to make the blob move to the center of the mouse.
without it the blob would move like this -
and with it it would move like this -
Now try moving your mouse near the card -
add few more cards and see the magic!
5. Additional effects
Now when you hover the cards it does nothing & its kinda boring so lets add a glow effect following the mouse -
first we will add a transition
property to smoothly transition into the :hover
state
.inner {
/* ... */
transition: background 300ms ease-in-out;
}
and on .card
:hover
we will change the background opacity and add a backdrop blur -
.card:hover > .inner {
background: rgb(26, 26, 26, 0.6);
backdrop-filter: blur(80px);
}
and now -
And there you have it!
Thanks for reading the blog! I hope it helped you :)
Top comments (2)
Waoh, nice effect and good tutorial!
this coll and i will try it