Animation » Example Animations » 33. Layout animation

33. Layout animation

Give a motion element a layout property and it will automatically animate when its position (or size) changes.

Code component

Here the divs are placed in a grid, so their actual position is defined by the grid. What makes them move around is the fact that their keys are changed.

(The code inside useEffect() will run when the items state changes, which will be every second because that’s when the setTimeout() inside it calls setItems() again.)

const itemsA = [1, 2, 3, 4]
const itemsB = [3, 1, 4, 2]
const itemsC = [4, 3, 2, 1]
const itemsD = [2, 4, 1, 3]

const colors = ["#f44", "#3f0", "#fb0", "#0ef"]

export default function CC_33_Layout_animation(props) {
    const [items, setItems] = useCycle(itemsA, itemsB, itemsC, itemsD)

    React.useEffect(() => {
        setTimeout(() => setItems(), 1000)
    }, [items])

    return (
        <div>
            <div
                style={{
                    display: "grid",
                    gridTemplateColumns: "auto auto",
                    gridGap: 10,
                }}
            >
                {items.map((item) => (
                    <motion.div
                        style={{
                            width: 75,
                            height: 75,
                            borderRadius: 20,
                            backgroundColor: colors[item - 1],
                        }}
                        key={item}
                        layout
                        transition={{
                            type: "spring",
                            stiffness: 350,
                            damping: 25,
                        }}
                    />
                ))}
            </div>
        </div>
    )
}

Code overrides

Automatic layout animations don’t work with code overrides. This example is included to demonstrate that.

const positions = [
    { top: 0, left: 0 },
    { top: 0, left: 85 },
    { top: 85, left: 85 },
    { top: 85, left: 0 },
]

const useStore = createStore({ position: 0 })

export const Container = (Component): ComponentType => {
    return (props) => {
        const [store, setStore] = useStore()

        useEffect(() => {
            setTimeout(() => setStore({ position: store.position + 1 }), 1000)
        }, [store])

        return <Component {...props} />
    }
}

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

        const [store, setStore] = useStore()

        return (
            <Component
                {...rest}
                layout
                style={{
                    ...style,
                    top: positions[(store.position + Number(name)) % 4].top,
                    left: positions[(store.position + Number(name)) % 4].left,
                }}
                transition={{ type: "spring", stiffness: 350, damping: 25 }}
            />
        )
    }
}


Leave a Reply