Visuals have always been a core part of any website’s design. The more interesting and informative they are, the better the user experience tends to be. Static images make up the bulk of that visual layer; however, animations have become increasingly popular nowadays.
Subtle hover effects and transitions can make a site feel dynamic and responsive, while smooth scroll cues and button animations can guide users towards CTAs and important content. In addition, larger animations can make a site look more alive and engaging, conveying much more context than a static image can.
However, they can also severely impact your Core Web Vitals scores and cost you search rankings and conversions if implemented carelessly. They do, after all, require more resources to render. The good news is, though, that with the right tools and techniques, you can have both: visually impressive pages and excellent performance.
This blog explores the best practices for animation-heavy websites without tanking your Core Web Vitals.
Why animations threaten Core Web Vitals and which metrics to watch
Before we talk about how to properly implement animations on your website, it’s vital to understand which specific metrics they tend to hurt, and why that is.
Google’s Core Web Vitals primarily measure four things: how fast your page’s main content appears (LCP), how quickly the page responds to user input (INP), how quickly your server responds (TTFB), and how much the page shifts (CLS). Animations can affect all three in different ways.
One thing is worth clarifying before we dive in, though. Core Web Vitals are browser-side metrics. They measure what happens on your visitor’s device after your server has already done its job and delivered the page. This is why you’ll see “browser” come up a lot in this article: that’s where the performance battle for animations actually occurs.
Hero animations can delay the Largest Contentful Paint
The first metric we want to take a look at is Largest Contentful Paint (LCP). It measures how long it takes for the biggest visible element on the screen to fully render. That can be a hero image, a heading, a large block of text, or an animation.
Google recommends an LCP of under 2.5 seconds, as per the guidelines we linked above. Much akin to how images can delay the rendering, animations do that in two ways:
If your hero section is built around a large animated element (e.g., video background), the browser can’t mark LCP as complete until that element loads.
If you are using a JavaScript animation library to fade in or slide your LCP element, there’s often a measurable delay between the element loading and the animation completing. From the browser’s perspective, such an invisible or partially-rendered element doesn’t count.
The obvious fix here is to ensure your largest element isn’t an animation of any kind, or to ensure it renders immediately without waiting for JavaScript. If the animation must be the largest element, keep reading to learn how to optimize it.
INP and why heavy scripts make your site feel unresponsive
The next metric is Interaction to Next Paint (INP). It measures how long it takes the browser to visually respond after a user interaction, such as clicking a button, tapping a menu, or submitting a form. It’s also the one most likely to “fail” on WordPress sites due to a wide number of reasons.
Google’s threshold for “good” is under 200ms, and animation libraries are a common culprit that ruins INP scores here. A JavaScript library (like GSAP, more on it in a bit) loaded globally—meaning for every single page, even if only used on a handful of them—still adds to the scripts the browser has to execute on every interaction.
The same goes for bloated page builders that register their own animation scripts site-wide, even on pages without animations. Yet, the scripts still execute, because they are on the page.
In short, unnecessary scripts slow down the browser, and a slow browser fails INP.
TTFB and the hosting layer underneath it all
Finally, Time to First Byte (TTFB) is how long it takes for the browser to receive the very first byte (the first piece) of your page’s HTML after making a request.
We know what you are thinking: TTFB isn’t a Core Web Vital, and you are correct. However, it’s a foundational web performance metric that’s worth noting. If TTFB is slow, everything else downstream is delayed, too, including any animation scripts the page needs to load.
Unlike the previous two metrics, TTFB is primarily a hosting and server-configuration problem. A slow host, an uncached WordPress installation, or a distant server can add hundreds of milliseconds before the browser even begins parsing your page.
Improving it typically means using a fast host with server-side caching, a CDN, and proper PHP configuration.
What about CLS?
Cumulative Layout Shift (CLS), which is a Core Web Vital, measures how visually stable a page is. In other words, how much the page’s layout shifts around as elements load in. Whether buttons change positions, text lines get disrupted, etc. We all know the frustration of trying to click a button just as it zips out of the way at the last second.
Google recommends less than 0.1. What does that number mean? The math behind it is beyond the scope of this blog, but to briefly explain it, it means a small element on the page moved a fraction. Simply put, minimal layout shifting. For a nitty-gritty explanation of how it works, the official Google documentation has it all.
When it comes to animations, all that you need to remember is:
Avoid animating properties that change the layout, like width, height, or margin. This is different from declaring them. Statically defining them on asset containers is actually good practice since it reserves space in the layout.
Use compositor-only properties like transform and opacity.
If you need to move elements, pre-allocate their space with containers or use absolute positioning. That way, they slide over content instead of pushing it around.
This quick CSS example showcases these points.
.sale-banner {
position: fixed;
top: 0;
width: 100%;
height: 50px;
transform: translateY(-100%);/* Starts hidden off-screen */
transition: transform 0.3s ease;
}
/* When you want it to slide down into view */
.sale-banner.is-active {
transform: translateY(0);
} This will make the animation slide smoothly into place when needed, rather than shoving elements around on the page. That will keep the page stable, with minimal visual shift.
Choosing the right animation tools
Now that we have a baseline of which metrics animations can affect on your site and their consequences, it’s high time we talked about some practical advice.
In this section, we’ll focus on a few options that will deliver solid animations without dragging your site’s performance to the ground.
GSAP with lazy loading
GreenSock Animation Platform (GSAP) is the industry-standard JavaScript animation library for serious web animation.
The library is fast and flexible, and capable of handling complex multi-step sequences, scroll-triggered effects, and SVG morphing. Of course, the cost is that it adds weight to the page, like any other JavaScript library.
To offset that, load this library only when it’s needed and only where it’s used. Avoid loading it globally (e.g., via your theme’s functions.php file) and instead load it conditionally on pages where animations are present.
In addition, you can use an Intersection Observer or a scroll-trigger threshold to delay the loading of the animated element until the user scrolls to it. This is also known as lazy loading.
Here’s an example JavaScript snippet to show what we described in practice.
// Example: lazy-initializing a GSAP animation with IntersectionObserver
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
gsap.from(entry.target, { opacity: 0, y: 40, duration: 0.6 });
observer.unobserve(entry.target);
}
});
}); document.querySelectorAll('.animate-on-scroll').forEach(el => observer.observe(el));
When done correctly, GSAP with lazy loading gives you powerful, butter-smooth animations with almost no impact on the Core Web Vitals for content that’s above the fold (on the screen). That’s because the script for everything under the fold never runs until the user gets to it.
Lottie: the complex, lightweight JSON animations
The Lottie library was developed by Airbnb (yes, the travel company), which renders animations exported from Adobe After Effects as small JSON files. It’s an alternative to GIFs or video for illustrations, loaders, icons, and decorative elements.
We say “alternative,” but in reality, we should have said “better alternative.” A Lottie animation is a fraction of the size of an equivalent GIF or video, and because it renders as a vector, it looks sharp on any screen resolution.
We have the perfect example to showcase how superior Lottie is to a GIF (let alone an MP4 file, which is even larger). We went to the free Lottie library and downloaded an asset (all credit to its creator). We then converted it to GIF with Lottie’s own converter. Here's a side-by-side of the results.





