Skip to main content

Framer Motion Integration

Using a state to do animations can be very expensive in terms of performance.

motion provides a way to control the styles/text without triggering re-renders. By using the MotionValue with useTransform and motion elements, you can update the value without triggering re-renders.

react-scrollytelling provides a wrapper around useSectionScroll() to update the MotionValue, so you can animate the element based on the scroll progress.

Example

Single Section

You can use useSectionScrollMotionValue() which returned updated MotionValue - scrolledRatioMotionValue based on the scroll progress:

import { useSectionScrollMotionValue } from '@react-scrollytelling/framer-motion';
import { motion, useTransform } from 'motion/react';

export const Section = () => {
const sectionRef = useRef<HTMLDivElement>(null);
const { scrolledRatioMotionValue } = useSectionScrollMotionValue(sectionRef);

// Transform the motion value for opacity
const opacity = useTransform(scrolledRatioMotionValue, (val) => 0.2 + 0.8 * val);

// Transform the motion value for border width
const borderWidth = useTransform(scrolledRatioMotionValue, (val) => `${Math.round(val * 6)}px`);

return (
<>
{/* Use MotionValue with a motion element to change the styles */}
<motion.section
ref={sectionRef}
style={{
opacity,
borderWidth,
}}
>
{/* ... */}
</motion.section>
</>
);
};

Example

  • scrolledRatio: 0

Multiple Sections

Example

You can simply the example in track grouped sections and use useActiveSectionMotionValue() to get the active section information and the updated MotionValue based on the scroll progress:

import { useActiveSectionMotionValue } from '@react-scrollytelling/framer-motion';

const { trackingId, scrolledRatioMotionValue } = useActiveSectionMotionValue();
You are viewing section
0
RED
ORANGE
YELLOW
GREEN
BLUE
PURPLE