Framer X » Animation » While Hover and While Tap

While Hover and While Tap

download the project with the examples

This is absolutely the easiest way to add interactivity to a Frame or Design Component. With just one line of code, you add an automatic animation between two states.

While Hover

Here’s an Override example. You give whileHover an object with the properties you want to animate, just like you did earlier with animate.

import { Override } from "framer"

export function WhileHover(): Override {
    return {
        whileHover: { scale: 0.8 },
    }
}
C01 – WhileHover

The Frame shrinks to 80% of its size when you hover over it and grows again when the hover ends.

With this one line of code you’ve added two animations:

  • one that happens when the pointer is over the Frame;
  • and a reverse animation that runs when the pointer leaves the Frame.

And here’s how you do it in a Code Component:

export function C01_WhileHover() {
    return (
        <Frame
            whileHover={{ scale: 0.8 }}
        />
    )
}

(The {{double curly braces}} are there because you’re writing the object directly inline.)

📑 whileHover

While Tap

The second one, whileTap, works the same, but then for taps.

And just like with animate, you can tweak these animations by adding transition settings.

import { Override } from "framer"

export function WhileTap(): Override {
    return {
        whileTap: { scale: 0.8 },
        transition: { duration: 0.5 },
    }
}
C02 – WhileTap

Here the Frame shrinks when you press down, but it will take its sweet little time of half a second to do it.

Also, the same thing happens when you release, the grow animation also has a duration of 0.5.

📑 whileTap

Both

Naturally, you can also use both whileHover and whileTap at the same time:

import { Override } from "framer"

export function WhileHover_WhileTap(): Override {
    return {
        whileHover: { radius: 75 },
        whileTap: { background: "Gold" },
    }
}
C03 – WhileHover and WhileTap

Variants

Now that we’ve already seen three ways to start an animation, we can talk about Variants.

You usually give animate (or whileHover, whileTap) an object with properties to animate to, something like, e.g. { rotate: 180 }.

With Variants, you can give those animation states a name, a variant label, and you tell animate (or whileHover, whileTap,…) to animate to that label.

const variants = {
    start: { rotate: 180 },
    hoverState: { radius: 75 },
    tapState: { background: "Gold" },
}

export function Variants(): Override {
    return {
        variants: variants,
        animate: "start",
        whileHover: "hoverState",
        whileTap: "tapState",
    }
}
C04 – Variants

For this to work you also need to provide the Frame with the variants themselves, though, so it knows that e.g., "start" stands for { rotate: 180 }.

Here the variants are written in a separate object (called variants), but as you’ll see in the next example, you can also write them inline.

Remember States?

In Framer Classic we had something similar to Variants: States.

However, ‘states’ already has a meaning in the React world (think of useState()), so the Framer team picked a different name.

As another aside: The Framer animation API is (partly) based on Popmotion’s Pose, an animation library for React. That library’s poses are the predecessor of Framer’s Variants.

📑 variants

Children

It gets even better when your Frame has children. When you give a child a set of Variants (with the same labels), it will animate simultaneously, automatically.

Here the Variants() Override is applied to the parent and Variants_Children() to the child.

// Override for the parent
export function Variants(): Override {
    return {
        variants: {
            start: { rotate: 180 },
            hoverState: { radius: 75 },
            tapState: { background: "Gold" },
        },
        animate: "start",
        whileHover: "hoverState",
        whileTap: "tapState",
    }
}

const childVariants = {
    start: { rotate: -180 },
    hoverState: { radius: 30 },
    tapState: { background: "Red" },
}

// Override for the child
export function Variants_Children(): Override {
    return {
        variants: childVariants,
    }
}
C05 – Variants and Children

The animatewhileHover, and whileTap properties are only set on the parent; all that the child needs is a set of (identically named) variants for this to work.

The parent’s "start" animation is a rotate to 180, but the child rotates to -180. Because of child’s counterclockwise rotation, it doesn’t seem to rotate at all.

Note: In the parent’s Override, I now wrote the variants inline (instead of in a separate const object).

Orchestration

You can orchestrate child animations with these transition settings:

  • with delayChildren, you insert a delay between the parent and child animations;
  • with staggerChildren, you add delays between the children animations themselves;
  • with staggerDirection, you decide which child to start with;
  • and with when, you can have the parent animate after the children.

This next example has three child Frames. Because of the delayChildren setting, the child animations start 0.2 seconds after the parent. And between the child animations is also a staggerChildren delay of 0.2 seconds.

// Override for the parent
export function Orchestration(): Override {
    return {
        variants: {
            initial: { skewX: -10, opacity: 0 },
            start: { skewX: 0, opacity: 1 },
            hoverState: { scale: 1.05 },
            tapState: {},
        },
        initial: "initial",
        animate: "start",
        whileHover: "hoverState",
        whileTap: "tapState",
        transition: {
            delayChildren: 0.2,
            staggerChildren: 0.2,
        },
    }
}

// Override for the children
export function Orchestration_Children(): Override {
    return {
        variants: {
            initial: { x: 50, opacity: 0 },
            start: { x: 0, opacity: 1 },
            tapState: { background: "Red" },
        },
    }
}
C06 – Orchestration

Note: only the parent has a "hoverState" variant label.

And also: the parent doesn’t have a "tapState" animation (there’s an empty {} object), but by setting a whileTap for the parent, the children do have one (with the same staggerChildren delay between them).

Initial

One more thing about this last example: It uses the initial property, which lets you define how a Frame should look when it appears.

initial accepts the same kind of values as animate, whileTap, etc. And as you can see: also variant labels.

It’s instrumental when you want an animation to start from opacity: 0 without having to dial down the Frame’s opacity on the Canvas.

📑 Orchestration, delayChildren, staggerChildren, staggerDirection, when, initial


Leave a Reply