# How do I animate an element when it scrolls into view with Framer Motion?

> Use the whileInView prop with initial: <motion.div initial={{ opacity: 0, y: 24 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true, amount: 0.3 }} />. For custom logic use the useInView hook, and for animation tied to scroll position use useScroll with useTransform.

Updated November 2026. Source: https://www.exodeui.com/questions/framer-motion-animate-on-scroll-into-view/

## Key takeaways

- whileInView animates when the element enters the viewport
- viewport.once runs it only the first time
- viewport.amount sets how much must be visible (0 to 1)
- useInView returns a boolean for your own logic
- useScroll and useTransform link motion to scroll position

## Frequently asked questions

### Why does whileInView fire again when I scroll back?

Set viewport={{ once: true }} so it only runs the first time.

### How do I trigger the animation earlier?

Use viewport.margin, for example margin: "0px 0px -100px 0px", or lower amount.

### Does whileInView hurt performance?

It uses IntersectionObserver, which is cheap. Animate transform and opacity, not layout properties.

### Can I do this without a library?

Yes. IntersectionObserver plus a CSS class works, and CSS scroll-driven animations cover many cases.

## Related

- [Best scroll animation libraries](https://www.exodeui.com/best-scroll-animation-libraries)
- [Stagger animation guide](https://www.exodeui.com/learn/stagger-animation)
- [Accessible motion and reduced motion](https://www.exodeui.com/learn/accessible-motion-reduced-motion)
- [AnimatePresence exit not working](https://www.exodeui.com/questions/animatepresence-exit-animation-not-working)
