JSFiddle - React, Tailwind, and code Playground

by Scott Kaye

HTML

<main>
	<button class="has-hover-sprite">Test button</button>
</main>

SCSS

$primary: #4a2bb4;

button {
	border: none;
	border-radius: 0;
	cursor: pointer;
	display: block;
	font-family: "Sofia Pro";
	font-size: 1.1em;
	font-weight: 600;
	line-height: 1.5em;
	min-width: 155px;
	outline: none;
	padding: 10px;
	text-align: center;
	text-transform: uppercase;
	transition: background 100ms ease;
	vertical-align: middle;
	width: 100%;
	background: $primary;
	color: #fff;
	overflow: hidden;
	position: relative;
}

.hover-sprite {
	background: radial-gradient(closest-side, #fff, transparent);
	width: 200px;
	height: 200px;
	position: absolute;
	top: 0;
	left: 0;
	pointer-events: none;
	transition: opacity 250ms ease;
	opacity: 0.1;
}

main {
	width: 300px;
	margin: 10px;
}

body {
	margin: 0;
	background: #414042;
}

JavaScript

document.querySelectorAll(".has-hover-sprite").forEach(el => {
	let sprite = document.createElement("div");
	sprite.className = "hover-sprite";
	el.appendChild(sprite);
	
	let size = sprite.getBoundingClientRect();
	
	el.addEventListener("mousemove", e => {
		sprite.style.left = e.offsetX - (size.width / 2) + "px";
		sprite.style.top = e.offsetY - (size.height / 2) + "px";
	}, false);
	
	el.addEventListener("mouseover", e => {
		sprite.classList.add("visible");
	}, false);
	
	el.addEventListener("mouseout", e => {
		sprite.classList.remove("visible");
	}, false);
});