Hover example: Step-by-step

Matt PerryMatt Perry

In this tutorial, we'll build the Hover example step-by-step.

This example is rated 1/5 difficulty, which means we'll spend some time explaining the Motion APIs that we've chosen to use (and why), and also any browser JavaScript APIs we encounter that might be unfamiliar to beginners.

Introduction

The Hover example demonstrates how to create a simple animation that triggers when a user hovers on and off an element.

In this example, we'll learn to use:

Why use hover?

Motion's hover function provides several advantages over traditional event listeners:

Simple API

hover automatically handle attaching and cleaning up event listeners. It also supports CSS selectors to add gestures to multiple elements at once.

hover(".box", (element) => {
    animate(element, { scale: 1.2 })
 
    return () => animate(element, { scale: 1 })
})

Touch filtering

For legacy reasons dating back to the first iPhones, browsers polyfill pointerenter and pointerleave events even from touch devices. So you can trigger :hover selectors from a touch pointer. This can lead to stuck or unexpected interactions.

hover automatically filters out touch events, so you can be sure that your animations will only trigger from mouse-like devices.

Get started

Let's begin with our basic HTML structure and styles:

<div class="box"></div>
 
<style>
    .box {
        width: 100px;
        height: 100px;
        background-color: #6100ff;
        border-radius: 10px;
    }
</style>

This creates a simple purple box that will be the target of our hover animation.

Let's animate!

Import from Motion

First, we need to import the necessary functions from Motion:

import { animate, hover } from "motion"

The hover function allows us to detect when an element is being hovered over and execute callback functions when hover begins and ends. The animate function will create our animations.

Setting up hover detection

Now, let's use the hover function to detect when our box is being hovered over:

hover(".box", (element) => {
    // Code to run when hover starts
 
    return () => {
        // Code to run when hover ends
    }
})

The hover function takes two arguments:

  1. A CSS selector or DOM element to watch for hover events
  2. A callback function that receives the target element

The callback function should return another function that will be called when the hover ends, allowing us to define both the "hover start" and "hover end" behaviors.

Adding animations

Let's define what happens when a user hovers over the box:

hover(".box", (element) => {
    animate(element, { scale: 1.3 })
 
    return () => animate(element, { scale: 1 })
})

When the hover starts, we animate the box to scale up to 1.3 times its original size. Motion animates scale with a spring animation by default for a natural, physical feel.

When the hover ends, we return a function that animates the box back to its original scale.

The complete code

Putting it all together:

<div class="box"></div>
 
<script type="module">
    import { animate, hover } from "motion"
 
    hover(".box", (element) => {
        animate(element, { scale: 1.3 })
 
        return () => animate(element, { scale: 1 })
    })
</script>
 
<style>
    .box {
        width: 100px;
        height: 100px;
        background-color: #6100ff;
        border-radius: 10px;
    }
</style>

Conclusion

In this example, we learned how to use Motion's hover and animate functions to create an engaging hover effect. The hover function makes it easy to detect when a user hovers over an element, and the animate function provides a clean way to create animations with spring physics.

This approach gives you more control than CSS hover effects while requiring much less code than vanilla JavaScript. You can expand on this by animating multiple properties, creating multi-stage animations, or combining hover with other gesture detectors.

Tutorial Project

We're currently working on adding a tutorial for every example on the Motion Examples website. So far, 12% of examples have a tutorial.