Framer Motion Mobile Performance: A Budget for Malaysian Users
Struggling with Framer Motion mobile performance on mid-range Androids? We share our performance budget, what to keep, what to cut, and how we improved our Lighthouse score.
Framer Motion is a fantastic library for creating fluid, complex animations on the web. But on the mobile devices common across Malaysia—think Samsung A-series or Xiaomi Redmi phones—those beautiful animations can quickly become a source of stutter, or 'jank'. The user experience suffers, and so do your Core Web Vitals.
At JRV Systems, we build for the Malaysian market. That means we can't assume every user has a flagship device. To tackle this, we developed a 'performance budget' for animations. It’s a simple framework for deciding which animations are worth the performance cost and which should be simplified or removed for mobile users.
The Cost of Animation on Mobile
Not all animations are created equal. The core challenge of Framer Motion mobile performance lies in understanding what happens under the hood. Most Framer Motion animations are driven by JavaScript, which runs on the browser's main thread. This is the same thread responsible for handling user input, running scripts, and laying out the page. If a complex animation keeps the main thread busy, the user's clicks and scrolls will feel delayed and the page will appear to stutter.
In contrast, simple CSS transitions on properties like transform and opacity can often be offloaded to the compositor thread, a process known as hardware acceleration. These animations run smoothly without blocking the main thread.
Heavy JavaScript animations can negatively impact key metrics like Interaction to Next Paint (INP), which measures responsiveness. A high INP score is a clear sign that your site feels slow to users.
Our Animation Budget: What's 'Free' vs. 'Expensive'
We categorize animations by their potential performance impact on a mid-range device. This helps our team make quick, consistent decisions.
-
Low-Cost (Generally Safe): These are animations that are typically hardware-accelerated and have a minimal impact on the main thread.
opacityandtransform(translateX, translateY, scale) animations on component load.whileHoverorwhileTapeffects, as they are direct user interactions.staggerChildrenon a small number of simple child elements.- Example: Fading in text blocks or icons as they enter the viewport.
-
Medium-Cost (Use With Caution): These animations are powerful but can cause jank if overused or applied to complex elements.
layoutanimations. While magical for reordering items or resizing containers, they can trigger costly browser reflows. We reserve these for critical UI elements where the effect is essential for user understanding.colororbackgroundColortransitions. These properties are not hardware-accelerated and trigger repaints, which can be slow.- Scroll-linked animations using
useScroll. These fire continuously on scroll and are a common cause of jank. If you must use them, ensure they are simple and only manipulatetransformoropacity.
-
High-Cost (Avoid on Mobile): These should be disabled or replaced with simpler alternatives on mobile devices.
- Complex SVG
pathLengthanimations. - Animations on large, complex components with dozens of nested, animated children.
- Any animation tied to scroll that affects properties other than transform/opacity (e.g., blurring an image, changing gradients).
- Complex SVG
Practical Steps for Better Performance
Budgeting is one thing; implementation is another. Here are concrete steps we take to improve Framer Motion mobile performance.
-
Prioritize Hardware Acceleration: Always favor animating
transformandopacity. If you have a component that animates frequently, you can give the browser a hint by addingwill-change: transform, opacity;to its CSS. -
Swap to CSS When Possible: For a simple button hover effect, do you really need to import the entire Framer Motion library? A standard CSS
transitionis often more performant for simple, non-interactive animations. -
Respect User Preferences: Use the
useReducedMotionhook to detect if the user has enabled the 'prefers-reduced-motion' setting in their operating system. For these users, you should disable non-essential animations. This is great for both accessibility and performance. -
Lazy Load Animated Components: If you have a heavy, animated component that's far down the page, use
React.lazy()and dynamicimport()to load it only when it's about to enter the viewport. If the user never scrolls that far, the code is never downloaded or parsed.
Case Study: Optimizing jrvsystems.app
We recently applied this thinking to our own website. Initially, we had a subtle, scroll-linked animation in our hero section. It looked great on our development machines, but testing on a mid-range Samsung phone revealed noticeable jank while scrolling past it.
-
Before: Our mobile Lighthouse performance score was around 78. Total Blocking Time (TBT) was higher than we liked, indicating that scripts were interfering with main thread responsiveness.
-
The Change: We replaced the expensive scroll-linked animation with a simple, on-load stagger animation for the heading and subheading. It achieves a similar dynamic feel but only runs once, freeing up the main thread during user scroll.
-
After: The jank was eliminated. The mobile Lighthouse score jumped to 91. TBT was significantly reduced, and the site felt immediately more responsive on our test devices. It was a clear win for user experience by making a targeted performance trade-off.
A Balanced Approach
Framer Motion is a powerful tool for building modern, engaging interfaces. The goal isn't to eliminate all motion, but to be deliberate. By using a performance budget, you can ensure your animations enhance the user experience rather than detract from it.
For us at JRV Systems, this means focusing on purposeful animations that provide feedback, guide the user, and improve usability—especially for our users here in Malaysia. A smooth, responsive experience on an everyday device is always better than a stuttering, complex animation on a flagship phone.