What you will learn

Motion Values

Framer’s animations work with so-called Motion values in the background, independently of React.

You can extract them from an animation and transform them, and you’ll often use them to make an animation follow a drag or scroll movement.

An example of reusing Motion values: The big box has a whileTap animation whose values I extracted to animate the rotatescale, and backgroundColor of the smaller boxes.

Motion values work independently of React. Here’s an example of using ‘state’ (like, e.g., React’s useState()) to change the width of the panels: It doesn’t work as smoothly, and you can’t ‘throw’ the handle.

And here’s a version that uses Motion values: It works much smoother because the animation works independently of React; no React state updates (resulting in a reload) are needed.

The handle’s position gets transformed to width values for the panels with useTransform().

Another example of the useTransform() hook.

Here a Scroll component rotates the boxes on the left: Scrolling 200 pixels results in a 360º rotation.

Plus, as you can see, you can clamp values or add an easing.

A Page component has the same Motion values as a Scroll. Here its horizontal scroll value, contentOffsetX, is used to animate the boxes on the pages.

Scroll-driven animations

With Framer Motion’s useScroll() hook, you can track a web page’s scrolling in three different ways:

  • Track the scrolling of the entire page — Page scroll
  • Track a scrollable element within the page — Element scroll
  • Track where an element currently is in the viewport — Element position

This works in React projects directly in a component, and on Framer Sites pages, you can use code overrides.

Page scroll

Scrolling this page changes:

  • The length of the SVG Path in the top right (+ the value inside it)
  • The position of the box (using CSS’s calc() function)
  • Its gradient (we’re interpolating between two different linear-gradient()s)
  • The box’s border radius (the box becomes a circle and then again a box)
  • The scroll distance value at the bottom of the screen

Element scroll

You can make an element in a webpage scrollable and follow that element’s scroll position.

Element position

There’s a third way to use useScroll(): Elements can track where they are in the browser’s viewport.

Here each picture’s position is used to change its size, opacity, and blur.

Plus, the name of each Buenos Aires barrio has its own effects: its x-position, opacity, and text shadow change.

Animating Motion values

With the animate() function, you can, well,… animate a Motion value. And whatever that Motion value is attached to will follow along.

Animating a Scroll component

Here we’re animating a Scroll with different transition settings:

  • Animating to the top with a duration of 1 second.
  • Animating to 200 using a ‘default spring’ with some extra stiffness.
  • Scrolling to 400 with a ‘duration-based spring’.
  • And to 600 with a custom Bézier curve.

Animating a Page component

Remember that earlier example? Here’s what happens when you animate its contentOffsetX (with some extra added bounciness).

Springy Motion values

With the useSpring() hook, you can create Motion values that will animate to a new value with a spring animation.

You usually create a Motion value with useMotionValue(), but you can also use useSpring(), and then it will be… springy.

Here ‘Rotate’ uses the default useSpring() settings, and ‘Scale’ got some extra stiffness.

You can use the same useSpring() hook to transform a standard Motion value into a bouncier one.

Here, ‘Rotate’ and ‘Scale’ are first converted to horizontal position animations and then made bouncier.