Framer Motion Mobile Performance: A Budget for Malaysian Users
Framer Motion creates beautiful animations but can degrade performance on mid-range Android phones. We share our practical budget for keeping sites fast in Malaysia.
Framer Motion is a powerful React library for creating fluid, complex animations. It's a tool we use at JRV Systems to add a layer of polish to user interfaces. However, with great power comes a significant performance cost, especially on the mid-range Android devices common across Malaysia.
Simply adding animations everywhere can make a website feel slow and unresponsive, ruining the user experience it was meant to improve. This is why we operate on a strict "performance budget" for animations. This article explains our approach to balancing aesthetics with speed, focusing on Framer Motion mobile performance.
Understanding the Performance Cost
When an animation runs in a browser, it consumes CPU and GPU resources. On high-end desktops or the latest iPhones, this is rarely an issue. On a three-year-old Android phone with a mid-tier processor, however, heavy JavaScript-driven animations can cause dropped frames, leading to a stuttering or "janky" experience.
Every animation that changes an element's geometry (like width, height, or margin) forces the browser to recalculate the layout of the page (a "reflow"). This is computationally expensive. Animations that change an element's appearance (like backgroundColor or box-shadow) require a "repaint." The least expensive animations are those that only affect the element's final composited layer, such as transform and opacity.
Framer Motion is excellent at optimising these animations, but it can't change the fundamental limitations of the browser rendering pipeline. The key is to be selective about what you animate.
The Performance Hierarchy: Cheap vs. Expensive Animations
Not all animations are created equal. We categorise them to decide where to spend our performance budget.
Cheap Animations (Use Freely): These properties are typically hardware-accelerated and handled by the GPU's compositor thread, meaning they don't block the main thread or trigger expensive reflows.
opacity: Fading elements in and out.transform: scale(): Scaling elements up or down.transform: translate(): Moving elements on the X and Y axes.transform: rotate(): Rotating elements.
Moderately Expensive Animations (Use Sparingly): These properties often trigger repaints but not full layout recalculations. Use them for small, short-lived effects, but avoid animating them on large or numerous elements simultaneously.
colorbackgroundColorbox-shadow
Very Expensive Animations (Avoid or Gate):
These are layout-altering properties. Framer Motion's layout prop is powerful for animating between different component states, but it is the most costly. Use it only for critical, user-initiated interactions where the effect provides significant value.
widthandheightpaddingandmargintop,left,right,bottomfilter: blur()(especially on large areas)
Our Practical Animation Budget at JRV Systems
For any given page, we follow a simple set of rules. This isn't a hard science, but a practical guideline that serves us well.
- On-load animations: Limit to a maximum of 3-5 subtle
opacityortransformanimations. A staggered fade-in for a list is a good example. We avoid any layout animations on page load. - On-scroll animations: Use
whileInViewfor simple fades and slides (opacityandtranslateY). The animation should be quick (e.g.,duration: 0.4) and should only run once. - On-hover/tap interactions: These are user-initiated, so a slightly higher cost is acceptable. A button scaling up (
scale: 1.05) or a card's shadow changing is fine. We still avoid animatingwidthorheight. - Complex layout animations: Reserve these for core UI elements where the visual feedback is essential, such as opening a modal, expanding an accordion, or reordering a list via drag-and-drop. These are moments where the user is actively engaged and expects a response from the interface.
Case Study: Optimising jrvsystems.app
When we first built our own website, we were excited to use Framer Motion. The initial version had several on-scroll layout animations and complex staggered transitions. On a developer's machine, it was flawless. On a Samsung Galaxy A12, it felt sluggish.
Our initial Lighthouse mobile performance score was around 78. The primary issues flagged were a high Total Blocking Time (TBT) and Cumulative Layout Shift (CLS) caused by our animations.
Our optimisation process was straightforward:
- We replaced all on-scroll animations that changed
heightormarginwith simpleopacityandtranslateYeffects. - We converted several decorative hover effects from Framer Motion to simple CSS transitions, which have a lower JavaScript overhead.
- We kept a single
layoutanimation for our services accordion, as it's a key interactive element.
After these changes, our Lighthouse mobile performance score consistently sits above 92. The site feels responsive and fast on the exact same mid-range devices, proving that a thoughtful approach to Framer Motion mobile performance yields tangible results.
Respecting User Preferences
Some users enable a "reduce motion" setting in their operating system due to motion sensitivity or simply to save battery. It's crucial to respect this preference.
Framer Motion provides a useReducedMotion hook that makes this easy. We wrap our more complex or non-essential animations in a conditional check:
const shouldReduceMotion = useReducedMotion()
Then, in our component, we can either disable the animation entirely or provide a simpler fallback (like a simple fade) if shouldReduceMotion is true.
animate={shouldReduceMotion ? { opacity: 1 } : { opacity: 1, y: 0 }}
This is not just a performance optimisation; it's an accessibility feature that demonstrates respect for the user.
Conclusion: Animate with Purpose
Framer Motion is an exceptional tool for building modern web interfaces. But like any tool, it must be used with discipline. By understanding the performance costs, creating a budget, and focusing animations on what matters most, you can deliver a polished and delightful experience without sacrificing speed for users in Malaysia and beyond.