All Articles

Text Shadow Animation on Mousemove

This is day 16 in my #javascript30 journey. This is the free course from Wes Bos that lets you brush up on your JavaScript skills via 30 projects.

Yesterday we worked on a local tapas ordering app that allowed us to explore LocalStorage and Event Delegation. You can keep track of all the projects we’re building here.

Today we’re exploring CSS Text Shadow Mouse Move Effect.


Day 16 - CSS Text Shadow Mouse Move Effect

Today’s goal is to make the text shadow on our header text follow the mouse around the window.

First, we will need to select the div (known as hero) & text. Then we need to listen for a mousemove change on the hero div. This will call the shadow function:

const hero = document.querySelector('.hero')  
const text = hero.querySelector('h1')

function shadow(e) {  
  //TODO: Magic
}

hero.addEventListener('mousemove', shadow)  
Shadow Function

To make the magic happen we need some specific data. We’re going to need the width & height of the hero div along with the current location of the mouse.

const { offsetWidth: width, offsetHeight: height } = hero  
let {offsetX: x, offsetY: y } = e  

There is some odd behaviour caused by the bubbling nature of JavaScript. When the mouse hovers over any children of the hero div the event fires as though the width & height of the child is the correct area. This is not what we want. Instead, we will normalize it so that it ignores mousemove events on children.

if(this !== e.target) {  
    x = x + e.target.offsetLeft
    y = y + e.target.offsetTop
  }

Set the maximum amount of movements. We need to set the maximum distance that we want the text shadow to move.

const movement = 100  

Then in our shadow() function:

//calculate the maximum movements that we want to happen (total set above)
const xMovement = (x / width * movement) - (movement / 2)  
const yMovement = (y / width * movement) - (movement / 2)

Now we can use these values to style the text shadow:

text.style.textShadow = `${xMovement}px ${yMovement}px 0 red`  

There we have a text shadow that follows us around the page:

FIRE!

We can always add some more text shadows in:

text.style.textShadow = `  
    ${xMovement}px ${yMovement}px 0 rgba(255, 0, 255, 0.7),
    ${xMovement * -1}px ${yMovement}px 0 rgba(0, 255, 255, 0.7),
    ${xMovement}px ${yMovement * -1}px 0 rgba(0, 255, 0, 0.7),
    ${xMovement * -1}px ${yMovement * -1}px 0 rgba(0, 0, 255, 0.7)`

This makes it an absolute spectacle:

trippy


Now that everything has been done I have pushed this project live to a Firebase project. You can view it live here.

You can keep track of all the projects in this JavaScript30 challenge here.