Ahmed Nadar

October 9, 2025

How I fixed an expensive CSS animations ⚡

Building Rails UI components with modern CSS and Hotwire? I help companies level up their front-end game with the Rails stack. Let's talk about your UI challenges →

CleanShot 2025-10-09 at 15.10.52.png


Last Tuesday, 1:32 PM. I'm deep in my component system, building yet another loading animation. You know the one, that smooth bar that slides across the screen while your data loads.

I write what feels natural:
.loading-bar {
  position: absolute;
  left: -100%;
  animation: slide 1.5s infinite;
}

@keyframes slide {
  from { left: -100%; }
  to { left: 100%; }
}

It looks good and sounded like: Looks fine on my machine™.

Then I switch tabs. Come back. And I see it.

The animation is... a bit chunky. Pixelated. Like watching a slideshow instead of a video. My smooth loading bar is stuttering across the screen like it's running on a 1998 Gateway computer. I remember that one, Windows 98 runs on Intel Pentium II @ 300MHz and 128MB RAM compare to now days it felt like 🐢

Here is the funny thing, I know about transform. Hell, I've used transform hundreds of times. But my brain was stuck on "I need to move this thing from left to right." Position. Direction. Movement. My thinking was trapped in the physical world.

So I did what we all do. I opened seventeen browser tabs.

And there it was, a Paul Irish article from 2012. He wrote: "It's more logical to move elements for design purposes (with transform) independent of your element layout (with position)."

That sentence hit different.

Here's what was actually happening every time my animation ran:
Frame 1: "Hey browser, move this element to -99% left"
Browser: "Okay, let me recalculate the entire page layout"
Frame 2: "Now move it to -98% left"
Browser: "Sure, let me recalculate the entire page layout again"
Frame 3: "Now -97%..."
Browser: Dies inside

Repeat this 60 times per second. My browser was having a panic attack.

When you animate with left, top, width, or height, you're asking the browser to pretend your entire webpage is made of Jenga blocks. Move one, and it needs to check if everything else needs to shift.

When you animate with transform, you're working with holograms. The element moves visually, but the browser knows nothing actually changed in the structure.

Here is how I fixed it:
.loading-bar {
  transform: translateX(-100%);
  animation: slide 1.5s infinite;
}

@keyframes slide {
  from { transform: translateX(-100%); }
  to { transform: translateX(100%); }
}


Three lines changed. That's it. The animation went from 24fps to 60fps. From janky to butter. From "is something wrong with my computer?" to "damn, that's smooth."

Here is what surprised me, visually. Open Chrome DevTools. Go to Rendering settings. Turn on "Paint Flashing." Now trigger your own animation:
With "direction" mine is left: your entire page lights up green like a Christmas tree. almost. The browser is repainting EVERYTHING.
With transform: only your animated element flashes, lightly sometimes not. Everything else chills.

That green flash? That's your CPU crying. That's your battery dying. That's your user/customer closing your tab.

Not like us human, computers are lucky to have two brains:
  • CPU known as The smart one. Handles logic, calculations, your JavaScript.
  • GPU aka the artist. Literally built to move pixels around.

When you use transform, the browser goes: "Hey GPU, move this thing for me." The GPU, built for this exact job, handles it without breaking a sweat. Easy peasy.

When you use left, everything stays on the CPU. The same CPU that's running your JavaScript, handling your network requests, and keeping seventeen browser tabs alive. I wonder, do you have more than 10 tabs open right now?

What about mobile? On my MacBook Pro, the difference was noticeable. I bet on some 3 year old phones, the difference would be everything.

What about your user? Your users aren't on your development machine. They're on old phones, phones, weak laptops, tablets running forty apps. Every frame counts.

Here are other bad animation habits:

The Width Animation
/* What I was doing */
@keyframes expand {
  from { width: 0; }
  to { width: 300px; }
}

/* What I should've done */
@keyframes expand {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

The Modal Slide
/* My old way */
.modal {
  /* this is everywhere */
  top: -100vh;  
  transition: top 0.3s;  
}
.modal.show {
  top: 0;
}

/* The correct way */
.modal {
  transform: translateY(-100vh);
  transition: transform 0.3s;
}
.modal.show {
  transform: translateY(0);
}

The Hover Effect
/* Triggering layout */
.card:hover {
  margin-top: -5px; /* I have see this in many apps/websites*/
}

/* GPU says "I got this" */
.card:hover {
  transform: translateY(-5px);
}

Rule of thumbs: the two properties you're allowed to animate
  1. transform
  2. opacity

That's it. That's the list. Everything else is expensive.
Want to move? transform: translate()
 Want to rotate? transform: rotate()
 Want to scale? transform: scale()
 Want to fade? opacity

Memorize this. Tattoo it. Put it on a sticky note.

How to Test This Right Now
  1. Open any project you're working on
  2. Find an animation
  3. Open DevTools → Performance
  4. Record your animation for 3 seconds
  5. Look for purple (Layout) and green (Paint) blocks

If you see them, you're doing it wrong. Switch to transform. Watch them disappear.

As I said previously, I knew about transform and I forgot it. I'd read about GPU acceleration. But when you're deep in component land, thinking about moving things left and right, your brain defaults to... left and right. 
It took a stuttering loading bar to remind me: the obvious solution isn't always the right solution.

✋🏼 Hey my future self:
Remember, every animation you write is a choice:
  • CPU vs GPU
  • 20fps vs 60fps
  • Battery drain vs efficiency
  • Janky vs smooth
Choose wisely. Your users' phones/old computers will thank you. And if you forget everything else, remember this: If you're animating anything other than transform or opacity, you're probably doing it wrong.

P.S. - It's been over a decade since Paul Irish wrote about this. We have new frameworks, new tools, new everything. But amazingly physics hasn't changed. The browser still needs to layout, paint, and composite. And transform is still king.

P.P.S. - Yes, this was me last Tuesday. Yes, I felt dumb. Yes, I went back and fixed other components. We all forget the basics sometimes.


Ahmed Nadar

About Ahmed Nadar

Ruby on Rails enthusiast at heart. I run RapidRails agency focus on Rails development & UI stack. Maker of RapidRails UI component for Ruby on Rails.
Find me on Twitter – @ahmednadar