Converting Figma Variants to CSS Keyframes

A practical guide to transform Figma variant animations into CSS keyframes without external libraries.

Feb 5, 2025 · 3 min read

I am working on a Figma plugin that helps anyone make animated smart components using preset templates. After getting all the main logic and basics to work, I ran into a problem: I needed to show users a preview of the animations before they added them to their designs and add to Figma.

At first, I thought, “I’ll just use Framer Motion or GSAP, like usual.” But when I checked out Figma’s Smart Animation system, I noticed something cool: the animations were really simple. Simple enough that I could build them with plain CSS—no extra libraries needed.

Here’s what I figured out about turning Figma animations into clean CSS, along with some code snippets that might help if you’re tackling something similar.

The Challenge

Making animations look smooth and consistent between design and development can be tricky. The goal here is to take Figma animations and translate them into CSS in a way that keeps the design looking good while using CSS’s built-in animation features.

The Key Difference

Figma’s animations work with variants and state changes, while CSS uses keyframes and animation properties. The trick is to find a way to match Figma’s animations to CSS so they look the same, but take advantage of what CSS can do.

The Figma Animation Structure

In Figma, animations are defined through a preset system that looks like this:

export const VARIANT_PRESETS = {
    "Fade In": {
        name: "Fade In",
        loop: false,
        variants: [{
            property: "State",
            states: [
                {
                    name: "state 1",
                    properties: {
                        opacity: 0,
                    },
                    transitions: [{
                        to: "state 2",
                        triggerType: "AFTER_TIMEOUT",
                        timeout: 0.2,
                        duration: 1,
                        easing: { type: "EASE_IN" }
                    }]
                },
                {
                    name: "state 2",
                    properties: {
                        opacity: 1,
                    },
                    transitions: [

                    ]
                }
            ]
        }]
    },
    .....
}

Mapping to CSS Animations

The key to successful mapping lies in understanding how to translate Figma's state-based animations into CSS keyframes. Here's how we can achieve this:

1. Creating Keyframes

For each animation preset, we create two versions: single-play and looping. This gives us flexibility in how the animation behaves:

@keyframes fade-in-single {
    0% { opacity: 0; }
    100% { opacity: 1; }
}

@keyframes fade-in-loop {
    0% { opacity: 0; }
    50% { opacity: 1; }
    100% { opacity: 0; }
}

2. Defining Animation Classes

We then create classes that apply these animations with appropriate timing:

.fade-in.single {
    animation: fade-in-single 0.75s linear forwards;
}

.fade-in.loop {
    animation: fade-in-loop 2s linear infinite;
}

Implementation in React

I'm using react to create all my Figma plugin. So, Once I map all the animation to css it's time to use this on the view where wanted to show the animation.

The implementation involves three main parts:

  • Animation Class Mapping
  • State Management
  • Dynamic Class Application

Here's how it comes together:

const getAnimationClass = (presetName) => {
    // Map preset names to CSS animation classes
    const classMap = {
        'Fade In': 'fade-in',
        'Fade Out': 'fade-out',
        'Zoom In': 'zoom-in',
        // ... other mappings
    };

    return classMap[presetName] || '';
};

// In your component
const getImageClasses = () => {
    if (!selectedPreset || !shouldAnimateImage) return '';
    
    const animationClass = getAnimationClass(selectedPreset);
    const iterationClass = isLoop ? 'loop' : 'single';
    
    return `${animationClass} ${iterationClass}`;
};

Handling Animation States

Finally, it’s time to handle states, like playing animations on hover or in a loop. A key part is managing how animations toggle between playing once or looping.

useEffect(() => {
    if (shouldAnimateImage && !isLoop) {
        const timer = setTimeout(() => {
            setShouldAnimateImage(false);
        }, 1000); // Adjust based on animation duration
        return () => clearTimeout(timer);
    }
}, [shouldAnimateImage, isLoop]);

Conclusion

To map Figma animations to CSS, you need to understand both systems and connect them. By using a clear, step-by-step approach, you can create smooth, easy-to-maintain animations that match the design while being fast and accessible.


WIP of the Project animate plugin

Here is Demo You can signup here

stay hungry, stay foolish

-Steve Jobs

©realvjyvijay verma