19
loading...
This website collects cookies to deliver better user experience
A production-ready motion library for React.
_app.js
- so all pages and other components. Where possible, using _app.js
to persist layouts between page changes will reduce the amount of rendering that React has to do each time the page changes - potentially improving your app performance.Moved common components that shouldn't animate on every page change into _app.js
. In my case this meant moving the Header
and Footer
which you can see on GitHub.
Added a wrapper component to control the animation states within pages. On my website it is the Layout
component. Note the <motion.main>
component which is specific to Framer Motion. In the rendered HTML output this will be a HTML main
element, however, adding the motion.
supplied by Framer Motion provides the ability to pass certain animation props such as transition
, initial
and animate
.
Layout
component you will see an object named variants
(see below). Variants promote cleaner code by removing the requirement to add the animation object to the motion.main
component. You can read more about them on the Framer Motion website.const variants = {
hidden: { opacity: 0, x: -200, y: 0 },
enter: { opacity: 1, x: 0, y: 0 },
exit: { opacity: 0, x: 0, y: -100 },
}
motion.main
component:<motion.main
variants={variants} // Pass the variant object into Framer Motion
initial="hidden" // Set the initial state to variants.hidden
animate="enter" // Animated state to variants.enter
exit="exit" // Exit state (used later) to variants.exit
transition={{ type: 'linear' }} // Set the transition to linear
className=""
>
{children}
</motion.main>
initial
and animate
states will control the entry animation for this component. When you change the page on my website, you should see the content change from having an opacity of 0
and x
position of -200px
to having an opacity of 1
and being in the center of the screen. This gives the effect of the content fading in from the left. By the way, "A Transition is an object that defines how values animate from one state to another" - from the Framer Motion website.AnimatePresence
and exit animations
AnimatePresence
component. For my website, I use the optional exitBeforeEnter
prop which tells the entrance animation to wait until the exit animation has ended before starting - without this the content would mount on top of the unmounting content, looking messy.AnimatePresence
component to the _app.js
file so that it never unmounts (unmounting would disable the exit animations). Note also the initial={false}
prop which disables the entry animation when you first visit the website. Disabling it is just a personal preference, remove that line if you want to enable it.AnimatePresence
is added to _app.js
, you can add an exit
animation to your motion.main
component. See this in the two code blocks above.Link
component. By default, when the Link
component is clicked it scrolls to the top of the page before animating, making the page transitions look a bit clunky. See below:Link
component that is used around your codebase, add the scroll={false}
prop. This will disable the scrolling when its clicked. To make this easier and maintain clean code, I created a component that wraps Link
but disables the scroll. I called it NoScrollLink
and you can view it on GitHub. Link
component's scroll, it's a good idea to scroll to the top of the page after the Framer Motion exit animation has completed. This gives the effect of content leaving at the current scroll height but the new content entering at the top of the page. Again this is easy, you can use the onExitComplete
prop on the AnimatePresence
component in _app.js
. The following code snippet will scroll to the top once the exit animation has completed.onExitComplete={() => window.scrollTo(0, 0)}
AnimatePresence
needed to be in _app.js
and how to stop the scroll to the top of the page after a Link
is clicked.