Boosting Framer Motion Performance & Accessibility 🚅💨
Łukasz Fiuk
Back in the good ol' days, we had to choose between fast websites or nicely animated websites. Well, those days are over, and we can have it all now 😎. And to make life even sweeter, we can also optimize accessibility of our animations with single prop 🌈
Quick note: Framer motion has great guides on that topic, so you might want to check those out instead 💀
Step 2: Lazy Load needed features 🦋
Replacing all your motion
tags with m
will break your animations as we are missing essential features. To fix that, we must first re-export the necessary Framer Motion features, as shown below:
💾 >_ tsx// Used for lazy-loading Framer motion features. // Docs: https://www.framer.com/motion/guide-reduce-bundle-size/#lazy-loading import { domAnimation } from "framer-motion"; export default domAnimation;
There are currently two feature packages you can load:
domAnimation
: This provides support for animations, variants, exit animations, and tap/hover/focus gestures. (+15kb)
domMax
: This provides support for all of the above, plus pan/drag gestures and layout animations. (+25kb)
Now let's put it all together. Open your top level component, eg. _app.tsx
load features and wrap your app with <LazyMotion/>
.
💾 >_ tsximport { LazyMotion } from "framer-motion" // Make sure to return the specific export containing the feature bundle. const loadFeatures = () => import("./features.js").then(res => res.default) // This animation will run when loadFeatures resolves. export const App = () => { return ( <LazyMotion features={loadFeatures} strict> <Component {...pageProps} /> </LazyMotion> ) }
Strict prop will throw errors ⚠️ if you, or anyone in your team will try lo load
motion
tags anywhere in your app. That's good because from now on you'd like to use lighter and optimizedm
tag.
Step 3: Optimizing Accessibility ♿
Since your app is already blazingly fast, we might spend a minute to optimize accessibility. 🌈 Adding <MotionConfig/>
with reducedMotion="user"
prop, will disable all animations except opacity
and background-color
for users who prefers reduced animations.
💾 >_ tsximport { LazyMotion, MotionConfig } from "framer-motion"; export const App = () => { return ( <MotionConfig reducedMotion="user"> <LazyMotion features={loadFeatures} strict> <Component {...pageProps} /> </LazyMotion> </MotionConfig> ); };
Wrapping Up 🍬
That's is folks - your animations are now fast, inclusive and sweet. 🍩 Happy Hecking! ✨
Comment System 💬
Having a way to engage with my audience was crucial for me, as thats one of the main reasons why I'm even building this blog. After some research I found two great options: Utterances and Giscus.
I ultimately decided to go with Giscus over Utterances because it's powered by GitHub Discussions, while Utterances uses Github Issues. (And I don't want to clutter Issues tab with comments)
With Giscus, each article generates a new discussion on GitHub where all comments are neatly organized.Thanks to GitHub Authentication there's no risk of bot-generated spam. On top of that it supports markdown, with familiar Github code highlighting and lazy-loading for faster page loads. 💨
I can't wait to see what kind of conversations will emerge in the comments section! 🤗