Text-shadow Film Effect
In this post, we’re going to cover a stylish cursor and text effect that I made for my portfolio site.
If you hover your mouse over the words, you’ll see what I’m talking about.
If you’re unable to interact with the jsfiddle, here is a .gif to demonstrate:
We’re going to code this text-shadow effect. To me, this is what a film projector looks like when it’s not working right and it’s a bit out of focus. I put this into my portfolio site because the effect reminds me of how technology can sometimes can be a little spooky.
If you’re viewing from a mobile phone, sorry, this tutorial requires a mouse!
- Event listeners
- CSS text-shadow
- X/Y coordinates and animation
All of this code can be found in a JS Fiddle, but here it is too.
(Just 2 divs)
(Some rules to center it)
Event Listeners are used to start and stop the shadow, and track the user’s mouse.
We’re going to be using 3 event listeners to achieve this: ‘
mouseout’ and ‘
To demonstrate what they do, start by moving your mouse over this red box.
- When your mouse enters the box, the box turns blue. This is the ‘mouseover’ event.
- When your mouse leaves the box, the box turns red again. This is the ‘mouseout’ event.
- While your mouse moves around inside the box, the X/Y coordinates of your mouse appear in the box and update every time your mouse moves. This is the ‘mousemove’ event.
If your’re unable to interact with the jsfiddle, here’s a .gif:
Text shadows need an X value, Y value, blur amount, and a color.
You’ve probably seen text shadows on really bad slideshow presentations.
Text-shadow is a CSS property that you can apply to any element with text inside of it. You give it an X coordinate amount, a Y coordinate amount, a size for the blurriness, and a color for the shadow.
Remember that X/Y coordinates start on the top-left and go towards the bottom right. So:
- Positive(+) X values make the shadow go to the right.
- Negative(-) X values make the shadow go left.
- Positive(+) Y values make the shadow go down.
- Negative(-) Y values make the shadow move up.
Click “Edit in JS Fiddle” if you’d like to play around with text-shadows a little bit.
Keeping the data organized.
So, if we need to keep track of an X value, a Y value, the blurriness amount, and a couple of other things, what’s the best way to do this?
This might be OK for small projects, but you would benefit from not getting into a habit of this. In larger projects, you can have collisions where you accidentally define 2 global variables with the same name.
If you use an object, it’s sort of like organizing your variables into their own special drawers. If you have a lot of variables describing similar things (maybe like
dogX), you can further specify which
y you’re talking about with an object’s namespace. If you have an object named
Cat.x will be namespaced to
Cat and will not collide with
Dog.x or even a variable just named
So this is why I use an object and get to call things like
Setting the text-shadow’s X/Y coordinates involves some math.
When the mouse moves over the text, we need to calculate the specific X/Y coordinates of the mouse relative to the center of the text.
Just a brief disclaimer. I hate math. When I do math, my heart rate increases, I get anxious, and I always have a flashback to sitting in some sort of wooden desk.
To make this calculation, we need to grab several measurements from the DOM.
For the Box’s height/width and coordinates, we’re going to use
getBoundClientRect(), which is a function you can call on any HTML element to obtain its measurements. It’s very useful!
To get the mouse’s X/Y coordinates on the page, we’re going to use
I can’t very effectively explain how the formulas work. Hopefully, the JS fiddle I provide here will allow you to intuitively grasp how the values we calculate from the mouse movements get put into the CSS text-shadow attribute.
Animating the blur with a setInterval.
Finally, we’re going to cover how to animate the blurriness to make the shadow look like it’s being projected by an out-of-focus film projector.
Before we begin, let’s pseudocode what’s happening here.
The animation depends on a lot of random number generation. Every 60ms (the speed of the animation), a new blur amount is rolled between 4-6px. At the same time, a second random number is rolled between 0-49. If it rolls a 0, the blur amount will be 1px which will bring the text into sharp focus for a single instant. To increase the chances of this happening, reduce the range to something like 0-10.
Just like with the coordinates of the text shadow, we’re going to save the blur amount into the
HoverData object and then pull that data into the text-shadow attribute. Instead of pulling the data every time the mouse moves, however, the data is updated every 60 milliseconds from the animation.
So there’s my explanation for how this effect works. I tried to cover as much as possible but if I missed anything please feel free to ask about it the comments.
Thanks for reading!