Animation » The Transition Property

The Transition Property

With the animate property, you define which properties should animate and to what value. How things should move — what you might call the ‘animation options’ — those you set with another property, transition.

📘 The Framer book – 💫 A: Animate | B: Transition | C: ‘while’ animations & Initial

 

An easing curve

When you move, rotate, or resize a frame or motion element (animating physical properties), it will, by default, happen with a spring animation. However, you can select a different type. Here I picked one of the easing curves: "anticipate".

export function An_easing_curve(Component): ComponentType {
    return (props) => {
        return (
            <Component
                {...props}
                animate={{ rotate: 45, scale: 1.5 }}
                transition={{ ease: "anticipate", duration: 2 }}
            />
        )
    }
}
B01 – An easing curve

It lets the frame move back a little — in anticipation of what’s about to happen.

Easing curves like this one (called tween curves) can also have a duration. I picked 2 seconds. When you omit duration, you’ll get the default value: 0.3 seconds.

More about the different tween curves

Transition, transition, Tween, duration

Spring settings

Let’s go back to that default spring. You can adjust a bunch of its settings; one of them is the spring’s damping ratio. The lower the value (the default is 10), the more it will oscillate. Here I changed it to 3:

export function Spring_settings(Component): ComponentType {
    return (props) => {
        return (
            <Component
                {...props}
                animate={{ scale: 1.5 }}
                transition={{ type: "spring", damping: 3 }}
            />
        )
    }
}
B02 – Spring settings

More about spring animations

Spring

Repeat and delay

Add a repeat value to make an animation run more than once. For instance, with a repeat of 2, the animation will run three times (two extra after the initial one).

Or you set it to Infinity and have it repeat till the end of time (or until you close the preview, whichever comes first).

export function Repeat_after_delay(Component): ComponentType {
    return (props) => {
        return (
            <Component
                {...props}
                animate={{ rotate: 360 }}
                transition={{
                    ease: "linear",
                    duration: 2,
                    repeat: Infinity,
                    delay: 1,
                }}
            />
        )
    }
}
B03 – Repeat after a delay

With delay, you add a pause before the start of the animation (also in seconds). It will only delay the beginning of the initial animation; and not insert pauses between the repetitions.

I gave this animation a "linear" easing to get a steady rotation at a constant speed.

delay, repeat

Delay between repetitions

You can also add a pause between the repetitions of a repeat, with another setting: repeatDelay.

With the below override, the frame will wait 1 second between every 2-second rotation:

export function Delay_between_repetitions(Component): ComponentType {
    return (props) => {
        return (
            <Component
                {...props}
                animate={{ rotate: 360 }}
                transition={{
                    duration: 2,
                    repeat: Infinity,
                    delay: 1,
                    repeatDelay: 1,
                }}
            />
        )
    }
}
B04 – Delay between repetitions

repeatDelay works with all three repeat types (more about those next).

repeatDelay

Repeat type and Bézier curves

Your animation can repeat in a few different ways. The default repeatType (used in the former examples) is "loop": the animation will just start over. The other two, "mirror" and "reverse", make it go back and forth.

Repeat types
"loop"The default type. The animation simply runs again.
"mirror"Flips the from and to values. The animation runs forward, backward, then forward again, etc. (This was called flip in earlier versions.)
"reverse"Does the same but also reverses the animation curve. So when the animation starts slowly, the reverse animation will end slowly.

"reverse" was called yoyo previously, which was fitting, as you can see in this example:

export function Reverse_with_Bezier(Component): ComponentType {
    return (props) => {
        const { style, ...rest } = props

        return (
            <Component
                {...rest}
                style={{ ...style, y: -90 }}
                animate={{ y: 70, rotate: 360 }}
                transition={{
                    delay: 1,
                    duration: 2,
                    ease: [0.075, 0.82, 0.165, 1],
                    repeat: Infinity,
                    repeatType: "reverse",
                }}
            />
        )
    }
}
B05 – Reverse animation with Bézier curve

repeatType

Bézier curves

Typically, you give ease one of the (11) predefined easing curves, like "anticipate", "easeOut", or "linear". But you can also give it an array with the four numbers that define a Bézier curve.

In this example, I used a stronger ease-out ([0.075, 0.82, 0.165, 1]) to make the yo-yo effect even more noticeable.

More about Bézier curves

Repeating spring animations

Since the change to this new repeatType syntax (in Framer Motion 2.5), you can also repeat spring animations.

Matt Perry posted this project as an example:

export default function App() {
    return (
        <motion.div
            className="handle"
            initial={{ x: -200 }}
            animate={{ x: 200 }}
            transition={{
                type: "spring",
                repeat: Infinity,
                repeatType: "mirror",
                repeatDelay: 0.1
            }}
        />
    );
}
Open in a new tab

Transition settings per property

The transition property is a bit like the animation options you could give a layer in Classic: it defines how all the frame’s properties will animate. However, you can override that global setting and provide distinct values for one or more properties, like here for rotate:

Example 1

export function Separate_transition_values_1(Component): ComponentType {
    return (props) => {
        const { style, ...rest } = props

        return (
            <Component
                {...rest}
                style={{ ...style, y: -90 }}
                animate={{
                    y: 70,
                    rotate: 360,
                }}
                transition={{
                    delay: 1,
                    duration: 2,
                    ease: [0.075, 0.82, 0.165, 1],
                    repeat: Infinity,
                    repeatType: "reverse",
                    rotate: {
                        delay: 1,
                        duration: 2,
                        ease: "linear",
                        repeat: Infinity,
                    },
                }}
            />
        )
    }
}
B06 – Separate transition values 1

When defining separate transition settings for a property, the global values will be ignored. That’s why the rotate animation now defaults back to a repeat type of "loop" (and also why we need to give it the same 1-second delay and 2-second duration).

Example 2

In this second example, I added a spring animation to a smaller scale of 0.8. Again, the globally set values are ignored (repeat, repeatType, …), so this scale animation runs just once.

export function Separate_transition_values_2(Component): ComponentType {
    return (props) => {
        const { style, ...rest } = props

        return (
            <Component
                {...rest}
                style={{ ...style, y: -90 }}
                animate={{
                    y: 70,
                    rotate: 360,
                    scale: 0.8,
                }}
                transition={{
                    delay: 1,
                    duration: 2,
                    ease: [0.075, 0.82, 0.165, 1],
                    repeat: Infinity,
                    repeatType: "reverse",
                    rotate: {
                        delay: 1,
                        duration: 2,
                        ease: "linear",
                        repeat: Infinity,
                    },
                    scale: { delay: 1, type: "spring", damping: 3 },
                }}
            />
        )
    }
}
B07 – Separate Transition values 2

Transition


Join the Framer book mailing list    ( Β± 6 emails/year )

GDPR

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing per their Privacy Policy and Terms.



9 comments on β€œThe Transition Property”

  • jeff.stone says:

    Hi Tes, how to set transition property for exit animation globally? I’m able to set transition globally using , but I want to target to “exit” animation specifically? Is it possible via ?

    • Tes Mat says:

      Hi! You can define global transition settings for a set of motion elements by putting them in a <MotionConfig> component. But I don’t think you can say that all exit animations should have a specific transition.

      In case you didn’t know: You can always include some transition settings in the object you pass to exit. Here’s an example with animate, but it works the same.

  • prokop says:

    Hi Tes,
    I’m having this basic override animation for (a black square) object. Everything’s fine. Until I go from Screen 1 to Screen 2 (where is applied override), then from Screen 2 back to Screen 1 during this animation, and back to Screen 2 – and all of the sudden animation stopped working. It works in Canvas, but when I place this prorotype to Web – it doesn’t working. Here’s the prototype https://emojis-irritate-982961.framer.app and here’s the code:

    • prokop says:
      export function Hide(Component): ComponentType {
          return (props) => {
              return (
                  <Component
                      {...props}
                      initial={{ opacity: 0 }}
                      animate={{
                          opacity: [0, 1, 1, 0],
                      }}
                      exit={{ opacity: 0 }}
                      transition={{
                          delay: 1,
                          duration: 3,
                          ease: [0.6, 0.2, 0.25, 1],
                          times: [0, 0.02, 0.98, 1],
                      }}
                  />
              )
          }
      }
    • Tes Mat says:

      Hi! Yeah, that’s normal because transitioning from screen to screen doesn’t reload a screen that was already visible.

      Your best option is probably to recreate the animation with transitions between screens. You can give an interaction a delay to have it wait a bit on a specific screen and use Appear interactions to move automatically to the next screen.

      • prokop says:

        Oh, interesting. Thank you Tes for your reply. This is exactly how I solved it. I was just trying to come up with some more elegant solution πŸ™‚ Nevertheless thanks again! πŸ™‚

  • akinsnuel says:

    hi I’ve been trying to set delay to a group of keyframes I wanted to ask if it was possible, let me explain the animation process is a sets of cards that reveals from a hidden div and goes back in but in different periods, so that only one shows at atime… but the complete cards are three

    • Tes Mat says:

      I suppose this could work by giving each card its own keyframe animation, but with a different delay (If they all animate the same, you could put the keyframe animation in a variant).

      If it doesn’t work out with delay, I would try to give cards times where they don’t animate, just by animating to the same keyframe value again or maybe tweak the timing using times.

Leave a Reply