Twelve fade-in keyframes in one stylesheet, and the fix

I recently jumped into a rescue mission for a high-traffic WooCommerce store. The site looked fine from the front, but the stylesheet was a mess. Within the first hour I found something that made my skin crawl: twelve separate @keyframes definitions for a simple fade-in. Twelve. Some were named fade-in, some fadeIn, and one was just show. Every developer who had touched the project over the last three years had written their own instead of checking whether one already existed.

That redundancy is worse than code bloat, it is a maintenance trap. In my 14 years of WordPress development I have watched it produce “ghost bugs” where an animation looks perfect in staging and breaks in production, because a new plugin loaded a stylesheet that overwrote a global keyframe name. That is the case for CSS Keyframes Tokens: one centralized, standardized way to handle motion across the whole project.

The global scope trap

CSS keyframes are always global, and that is the part most devs forget. Even with “scoped” styles in a component-based architecture, the keyframe name itself lives in the global namespace. If two components define @keyframes pulse, the last one loaded wins. That is how you end up with a “pulse” animation that suddenly jumps 20% in size because somebody added a footer widget to the page.

My first instinct on that WooCommerce project was to rename everything with unique IDs. Wrong call: it grew the CSS file by another 40KB. The better fix is to treat animations the way you already treat colors or typography, with a single source of truth built on modern CSS architecture.

Standardizing with dynamic keyframes tokens

Instead of letting every component define its own motion, everything goes into one centralized bbioon-tokens.css file. The animations in it are not static either. CSS custom properties make them dynamic, so a single keyframe definition covers a lot of variations.

/* bbioon-tokens.css */

/* 
 * Slide In - Directional motion token
 * Default: Enters from left (-100%)
 */
@keyframes bbioon-slide-in {
  from {
    translate: var(--bbioon-slide-from, -100% 0);
    opacity: var(--bbioon-slide-opacity-start, 0);
  }
  to {
    translate: 0 0;
    opacity: 1;
  }
}

/* 
 * Spin - Continuous rotation token
 */
@keyframes bbioon-spin {
  from { rotate: 0deg; }
  to { rotate: calc(360deg * var(--bbioon-spin-turns, 1)); }
}

When you need a slide-in from the top for a notification, or one from the right for a cart drawer, you do not write new keyframes. You change the variables. It is the same approach I took in my guide on mastering modern CSS features.

Advanced composition and reduced motion

One common pitfall is animating the same property with two different tokens. Apply a “fade” and a “zoom” that both touch opacity, and CSS will normally drop the first one. The fix is animation-composition: add;, which saves a lot of pain in complex UI work. The MDN docs on animation-composition cover the details.

Accessibility belongs in the same file. Some people find motion physically nauseating, and there is no reason to force it on them. With prefers-reduced-motion baked into the tokens file, the whole site respects that setting without one extra line inside any component.

/* bbioon-tokens.css - Accessibility Layer */
@media (prefers-reduced-motion: reduce) {
  @keyframes bbioon-slide-in {
    from, to {
      translate: 0 0;
      opacity: 1;
    }
  }
}

Wrapped like that, the element simply “appears” for anyone with reduced motion turned on, while everyone else gets the smooth slide. That is what an enterprise-grade motion system looks like in practice.

The short version

Treating your animations as structured tokens is about building something that does not break the moment another stylesheet loads. Here is the checklist I run on a new project:

  • Prefix everything with a namespace like bbioon- so global names cannot collide.
  • Do not hardcode values in your keyframes. Use var() with sensible defaults.
  • Handle prefers-reduced-motion at the token level, not the component level.
  • Comment the file so the next dev knows which variables to tweak.

Motion systems get complicated fast, and most agencies wing it until the technical debt comes due. If you are tired of debugging a messy codebase and want a site built for scale, I have solved these exact problems dozens of times. Drop me a line and we will clean up that stylesheet.

How are you handling animation naming in your projects at the moment, and are you still fighting the global scope trap?

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.