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 rotate
, scale
, 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 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.
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.