Search

The Animate Property

The Animate Property

Basic animation

The easiest way to animate an element, is to set some values on animate.

export function Example() {
    return (
        <Center>
            <motion.div
                style={{
                    width: 150,
                    height: 150,
                    borderRadius: 30,
                    backgroundColor: "#fff",
                    position: "absolute"
                }}
                animate={{
                    left: 10,
                    top: 10,
                    scale: 0.5,
                    rotate: 45,
                    backgroundColor: "#ffd700"
                }}
            />
        </Center>
    );
}
The animate property
open in CodeSandbox

Whenever you give animate new values, the motion.div will animate to those values.

Now, this animation happens immediately, the moment the element becomes visible. But we’ll look at how you can trigger it with an event.

animate

Obviously, there’s more code here because I’ve also had so set visual and positioning properties. So in upcoming examples, I’ll often only show the animation code, like this:

export function Example() {
    return (
        <Center>
            <motion.div
                animate={{
                    left: 10,
                    top: 10,
                    scale: 0.5,
                    rotate: 45,
                    backgroundColor: "#ffd700"
                }}
            />
        </Center>
    );
}

But you can always find the complete code in the CodeSandbox.

Transform properties

Above I used the left and top properties to animate the div’s position, but it’s actually better to use x and y for this. With these, what they call, transform properties, animations will run smoother (GPU accelerated).

They also have the advantage of starting from zero, so moving an element 10 points to the right is as simple as x: 10. Other GPU-accelerated transform properties are: scale, scaleX, scaleY, rotate, rotateX, rotateY, skewX, and skewY.

export function Example() {
    return (
        <motion.div
            animate={{ scaleY: 0.5, scaleX: 2, skewX: -6, y: -120 }}
        />
    );
}
The animate property – Transform properties
open in CodeSandbox

Transform

Transform origin

These transforms (scaling, rotating, and skewing) will happen from the element’s transformation origin. By default, this is the center, but you can change that.

Here I placed the originY at the top of the div so that the (x-axis) rotation happens with that edge as the center point.

export function Example() {
    return (
        <div>
            <motion.div
                style={{
                    width: 150,
                    height: 150,
                    borderRadius: 30,
                    backgroundColor: "#fff",
                    originY: 0
                }}
                animate={{ rotateX: 360 }}
            />
        </div>
    );
}
The animate property – Transform origin
open in CodeSandbox

By the way, I applied some perspective to its parent div to make the animation look three-dimensional:

export function Example() {
    return (
        <div
            style={{
                width: "100%",
                height: "100%",
                display: "flex",
                placeItems: "center",
                placeContent: "center",
                perspective: 600
            }}
        >
            <motion.div
                style={{
                    width: 150,
                    height: 150,
                    borderRadius: 30,
                    backgroundColor: "#fff",
                    originY: 0
                }}
                animate={{ rotateX: 360 }}
            />
        </div>
    );
}

Transform origin
transform-origin perspective

Colors

Just like you can change a div’s backgroundColor, you can also animate it. As always, you write the color as a text string, in any of these CSS color formats:

  • Hex Code — “#00ff00”
  • Websafe Hex Code — “#0f0”
  • RGB Decimal — “rgb(0, 255, 0)”
  • RGBA Decimal — “rgba(0, 255, 0, 1)” (the last value is ‘alpha’)
  • Hue Saturation Lightness — “hsl(120, 100%, 50%)”
  • Hue Saturation Lightness Alpha — “hsla(120, 100%, 50%, 1)”
export function Example() {
    return (
        <div>
            <motion.div
                animate={{ backgroundColor: "#ff6347" }}
            />
            <motion.div
                animate={{ backgroundColor: "hsl(290, 50%, 60%)" }}
            />
            <motion.div
                animate={{ backgroundColor: "rgba(153, 204, 102, 0.8)" }}
            />
        </div>
    );
}
The animate property – Colors
open in CodeSandbox

You can also animate between different color formats, like from a HEX to an RGB value.

Pro tip: You can’t animate with CSS named colors like, e.g., “Tomato”.

Supported Values
background background-color

Complex values

Some CSS values are more complex. For example, a CSS boxShadow is also written as a string, but this string can contain the shadow’s x- and y-offset, blur, spread, and color.

You can animate all these values simultaneously if you stick to one kind of notation. Take this example:

export function Example() {
    return (
        <motion.div
            style={{
                width: 150,
                height: 150,
                borderRadius: 30,
                backgroundColor: "#fff",
                // Initial shadow
                boxShadow: "0px -300px 80px 100px rgba(255, 255, 255, .3)"
            }}
            initial={{ backgroundColor: "#fff" }}
            animate={{
                backgroundColor: "#08f",
                // Animation
                boxShadow: "0px 0px 80px 30px #fff"
            }}
        />
    );
}
The animate property – Complex values
open in CodeSandbox

Its initial shadow (set on style) is:

"0px -300px 80px 100px rgba(255, 255, 255, .3)"

Which stands for:

  • 0px — x-offset
  • -300px — y-offset
  • 80px — blur radius
  • 100px — spread,
  • and rgba(255, 255, 255, .3) as the color.

… so I had to animate to a shadow defined with the same five values:

"0px 0px 80px 30px #fff"

Animating to a shadow written in the shorter ‘just x- and y-offset and color’ form (also possible in CSS) would not work.

"0px 0px #fff"

Supported Values, style
boxShadow

Adding state

Of course, you don’t always have to animate an element when it appears. Whatever you pass to animate can be saved in a useState() so that you can change it.

State: A Component’s Memory, useState()

Example 1

Here’s an additive animation. 45 is added to the degrees state every time you tap, making the div rotate.

export function Example() {
    const [degrees, setDegrees] = useState(0);

    function add45() {
        setDegrees(degrees + 45);
    }

    return (
        <motion.div
            animate={{ rotate: degrees }}
            onTap={add45}
        />
    );
}
The animate property – Using the current state 1
open in CodeSandbox

Example 2

In this second example, the motion div will rotate when you pan it (panning is like dragging, but without the div going anywhere 😉).

Framer Motion’s onPan() event returns two things: a common MouseEvent (or TouchEvent) object and a special PanInfo object that contains (among other things) a delta of points that the pointer moved since the last event.

I named that second object info, so the distance traveled since the last time onPan() was called will be in info.delta.x.

Since Framer Motion 11, this doesn’t animate well, so here we’re changing rotate directly in the <div>’s style.

export function Example() {
    const [degrees, setDegrees] = useState(0);

    return (
        <motion.div
            style={{
                width: 150,
                height: 150,
                borderRadius: 30,
                backgroundColor: "#fff",
                color: "#999",
                fontSize: "40px",
                display: "flex",
                placeItems: "center",
                placeContent: "center",
                cursor: "ew-resize",
                rotate: degrees
            }}
            onPan={(_, info) => setDegrees(degrees + info.delta.x)}
        >
            {Math.round(degrees)}
        </motion.div>
    );
}
The animate property – Using the current state 2
open in CodeSandbox

This onPan() event is called continuously, so delta.x will contain small values, like 1 point, another point, -1 point when panning to the left, or often: 0 points. Every time onPan() is called, that delta is added to the current number of degrees with setDegrees(). Thus, when you pan to the right, the div rotates clockwise, and when panning left, counterclockwise.

(JavaScript’s Math.round() function converts the decimal value of degrees to an integer.)

onPan()
Math.round()

Multiple properties

You don’t have to create an useState() for every property you want to animate, you can also put a set of properties in an object (here, it contains values for both scale and rotate).

export function Example() {
    const [animate, setAnimate] = useState({ scale: 1, rotate: 0 });

    return (
        <motion.div
            animate={animate}
            onTapStart={() => setAnimate({ scale: 1.25, rotate: 90 })}
            onTap={() => setAnimate({ scale: 1, rotate: 0 })}
        />
    );
}
The animate property – Multiple properties
open in CodeSandbox

You probably know that an onTap() event gets triggered when you release your finger; at the end of the tap gesture. And there’s another event that gets triggered at the beginning, when you press down: onTapStart().

onTapStart(), onTap()

Using useState() purely for… state

In the previous examples, we’ve used useState() to animate just one property (scale) or an object that contains multiple properties (scale and rotate).

But you can use useState() to keep track of just the state. Meaning something like ”Is the switch on or off?” or, in the following example, “Is the box dragged right now?”

The animate property – Separate useState() for each property
open in CodeSandbox

Here we’re switching between two states: dragging or not, yes or no, so we can use a simple Boolean for this.

export function Example() {
    const [dragging, setDragging] = useState(false);

    return (
        <motion.div
            animate={{ backgroundColor: dragging ? "#a0f" : "#04f" }}
            transition={{ duration: 0.5 }}
        >
            <motion.div
                drag
                dragConstraints={{ top: -140, right: 140, bottom: 140, left: -140 }}
                animate={{ scale: dragging ? 1 : 0.8 }}
                onDragStart={() => setDragging(true)}
                onDragEnd={() => setDragging(false)}
            />
        </motion.div>
    );
}
The animate property – Using useState() only for state
open in CodeSandbox

The parent’s backgroundColor is now set inline, with a ternary operator (a concise way of writing an if…else conditional). When dragging is true, it will animate to the first color (“#a0f”), and when not, it animates to the second color (“#04f”).

And the same happens with the draggable div’s scale: when dragging is true, it will be 1, and when false, it’ll be the smaller 0.8.

drag, dragConstraints, onDragStart(), onDragEnd()
Conditional (ternary) operator, if…else

Which properties can you animate?

A bunch more properties can be animated. Check the Animatable Properties page for an overview.

Leave a Reply

Scroll to Top