This site uses third-party cookies, learn more or accept

Eye Following Mouse SVG Animation Tutorial

Want to make a snazzy animation where the eyes on a vector graphic follow the user's mouse? Find out how!
Written by Maxwell Pelic,

I just revamped my website, including a new color scheme and more consistent layout, but one of my favorite parts is the animation on the home page where a vector graphic of me looks around at the user’s mouse and occasionally blinks. Although this might seem complicated at first, it was pretty simple to get working and makes the page come alive.


The first thing you’ll need is a vector graphic with some simple eye elements. The eyes need to be in a clipping mask, so when they move around they don’t move outside of their domain. Once you have the SVG, make sure you embed it in the HTML document instead of linking to it, since the content is not editable when linked in the page.

Next, look through the SVG file to find the eye elements. In my case, I discovered that they had the classes .cls-6 and .cls-3, so in this example we’ll use those. The easiest way to find them might be identifying the colors of the iris and pupil and then looking through the SVG’s style data to see what element those colors line up with.


The first part of the animation is querying the elements and getting their starting positions, so you can figure out how far they should move:

const eye_elements = document.querySelectorAll(".cls-3, .cls-6");
const starting_positions = [];
for(let i = 0; i < eye_elements.length; i++){

Note: if you’re SVG dynamically resizes or moves around, you’ll need to update the starting positions every time the SVG moves. In my case I was already resetting the SVG every few seconds, so I didn’t worry about it.

Mouse Event

The next step is to listen for mouse events and update the positions accordingly. I found the best way to do this was the mousemove event, but that just depends on when you want the SVG to move it’s eyes.

//maximum distance you want the eyes to move
const MAX_DISTANCE = 10;
window.addEventListener('mousemove', e => {
    //loop through the eye elements
    for(let i = 0; i < eye_elements.length; i++){

        //get the mouse position relative to the eye element starting position
        const distance_x = starting_positions[i].x - e.clientX;
        const distance_y = starting_positions[i].y - e.clientY;

        //get the angle from the mouse position
        const angle = Math.atan2(distance_y, distance_x);

        //get the distance to the mouse (since the eyes should not move past the mouse)
        let distance = Math.sqrt(distance_x * distance_x + distance_y * distance_y);

        //limit the eye movement so they point to the mouse instead of moving to it
        distance = Math.min(distance, MAX_DISTANCE);

        //move the element
        eye_elements[i].style.transform = 
        `translate(${Math.cos(angle) * distance}px, ${Math.sin(angle) * distance}px)`;

Finishing Touches

To wrap things up, let’s add a short transition to the eye elements to keep them from being choppy movements:

.cls-3, .cls-6{
    transition: transform 0.1s;

Previous Article: If you aren't using this word to start your Antiwordle game, you're not getting your best score.

Next Article: My Custom JavaScript Library _