Spotlight effect with JS and CSS
David Lange
Posted on April 29, 2022
Spotlight effects can be a pretty creative way of revealing content on your website. And they're surprisingly easy to create with a little JS and CSS!
The basic idea
TLDR; Use CSS radial gradient backgrounds, and then use JS to track the mouse movement and move the center of the gradient.
There are other, more complex ways of doing this - you could use canvas or external libraries - but I find the simpler approach is a good starting point and should work well enough for most use cases.
Let's get started:
#spotlight {
position: fixed;
opacity: 1;
width: 100vw;
height: 100vh;
top: 0;
left: 0;
pointer-events: none;
}
<div id="spotlight"></div>
const spotlightEl = document.querySelector("#spotlight");
function handleMouseMove(event) {
const { clientX, clientY } = event;
spotlightEl.style.background = `radial-gradient(circle at ${clientX}px ${clientY}px, #00000000 10px, #000000ee 350px)`;
}
document.addEventListener("mousemove", handleMouseMove)
And...that's pretty much it.
The #spotlight
div is positioned so that it always covers the entire viewport. We then attach an event listener to listen to the mouse's movement, and set the X
and Y
directly in the radial-gradient
CSS value.
The #00000000 10px, #000000ee 350px
part basically means we want a gradient that is transparent at it's center, and at 350px from the center is a slightly transparent black. That's how the gradient center reveals what's beneath.
Making it configurable
So far we have a basic spotlight, so let's go ahead and improve it.
We can create a Spotlight
class that allows you to easily set up new spotlights and pass in some options:
-
toggleEl
is the id of the element you want to use as a trigger to toggle the spotlight. -
innerRadius
andouterRadius
set the spotlight size. -
outerColor
sets the background color (try passing inred
for a truly bleeding edge experience).
The class also provides methods for switching the spolight on and off.
Making the light feel more natural
To make it a look a little more natural, there are a couple of added touches.
First, there is a slight delay in the spotlight movement. This adds a sense of weight to the light, like we're dragging it around with our mouse.
handleMouseMove(event: MouseEvent) {
setTimeout(() => {
this.updateEl(event.clientX, event.clientY);
}, 50);
}
Also, you'll notice the light "pulses" slightly - continually increasing and decreasing.
But how do we get it to work?
My first instinct was to animate the gradient size, but that's not actually possible in CSS! Next I thought of somehow changing the outerRadius
value in steps inside a function called in a setInterval
, but that turned out to be a really stupid idea. Finally, I came up with the simple solution - animate the scale of the entire spotlight div with a CSS animation.
@keyframes pulse {
0% {
transform: scale(1);
}
100% {
transform: scale(1.1);
}
}
this.el.style.animation =
"pulse 3s ease-in-out infinite alternate forwards";
This way, we don't need to touch the actual gradient, we just animate the entire "canvas", stretching the gradient in the process. I also used CSS animations for the "switching on/off" part.
Wrapping up
Obviously, you shouldn't be using spotlights in every single page (please don't!). But when used right, they're a nice way for users to feel like they're discovering some cool concealed content for the first time.
Thanks for reading!
Posted on April 29, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.