<h1>
Hover over each of the buttons to see the effect in action.</h1>
<div class="display">
<a class="HOVER">
<span></span>
<text>Hover Me!</text>
</a>
<a class="HOVER">
<span></span>
<text>Hover Me!</text>
</a>
<a class="HOVER">
<span></span>
<text>Hover Me!</text>
</a>
<a class="HOVER FLASH">
<span></span>
<text>Don't Hover Me!</text>
</a>
</div>
<footer>
<div class="link">Did you like this? Check out my other projects <a href="https://codepen.io/ViktorKorolyuk" target="_blank">here</a></div>
</footer>
css
@keyframes shake {
25% {
transform: rotate(calc(var(--angle) * -1));
}
50% {
transform: rotate(var(--angle));
}
100% {
transform: rotate(0deg);
}
}
body {
font: 100 1.3em sans-serif;
display: flex;
flex-direction: column;
align-content: center;
padding: 0 5rem;
}
h1 {
font-weight: 100;
}
.display {
display: grid;
grid-template-columns: 50% 50%;
gap: 0.1em;
}
.HOVER {
--width: 100%;
--time: 0.7s;
position: relative;
display: inline-block;
height: 1em;
padding: 1em;
color: white;
background: #222;
overflow: hidden;
}
.HOVER text {
position: relative;
z-index: 5;
transition: color var(--time);
}
.HOVER:hover text {
color: #222;
}
.HOVER span {
position: absolute;
display: block;
content: "";
z-index: 0;
width: 0;
height: 0;
border-radius: 100%;
background: #fff;
transform: translate(-50%, -50%);
transition: width var(--time), padding-top var(--time);
}
.HOVER:hover span {
width: calc(var(--width) * 2.25);
padding-top: calc(var(--width) * 2.25);
}
.HOVER.FLASH:hover text {
color: white;
}
.HOVER.FLASH span {
background: #ff3b3b;
}
.animated {
--angle: 5deg;
animation: shake 0.3s;
}
.link{
position: absolute;
right: 10px;
bottom: 10px;
font-size: 1rem;
}
js
const ANIMATEDCLASSNAME = "animated";
const ELEMENTS = document.querySelectorAll(".HOVER");
const ELEMENTS_SPAN = [];
ELEMENTS.forEach((element, index) => {
let addAnimation = false;
// Elements that contain the "FLASH" class, add a listener to remove
// animation-class when the animation ends
if (element.classList[1] == "FLASH") {
element.addEventListener("animationend", e => {
element.classList.remove(ANIMATEDCLASSNAME);
});
addAnimation = true;
}
// If The span element for this element does not exist in the array, add it.
if (!ELEMENTS_SPAN[index])
ELEMENTS_SPAN[index] = element.querySelector("span");
element.addEventListener("mouseover", e => {
ELEMENTS_SPAN[index].style.left = e.pageX - element.offsetLeft + "px";
ELEMENTS_SPAN[index].style.top = e.pageY - element.offsetTop + "px";
// Add an animation-class to animate via CSS.
if (addAnimation) element.classList.add(ANIMATEDCLASSNAME);
});
element.addEventListener("mouseout", e => {
ELEMENTS_SPAN[index].style.left = e.pageX - element.offsetLeft + "px";
ELEMENTS_SPAN[index].style.top = e.pageY - element.offsetTop + "px";
});
});