Recreating Google Gemini Loading Animation in CSS & Tailwind

I want to give a sincere appreciation to the person who designed the Gemini loading animation. It is such a clean animation that I had to attempt to implement myself. It won’t be a exact match but close enough for my purpose. Here is the animation taken from Google Gemini implemented in CSS and Tailwind for my people :

(Refresh for the initial animation)

First in regular CSS

The animation is composed of two keyframes: expanding and moving.

  1. expanding keyframe is responsible for the initial sliding animation. We set the scaleX to 0 (meaning it is not visible on the X-axis) and opacity to 0 (to create a fade in effect ). I chose to scale it because if you do it by width, every loading bar would essentially have the same width. By scaling it, it would return back to its original width set.

  2. moving keyframe is responsible for the loading gradient effect. It basically moves the background gradient from left to right on a infinite loop. The background-size is set at 200% because if you only do 100%, you can see a skipping/jumping effect in the gradient. The animation begins with the background-position at 0% and moves to -200% because we want the loading animation to look like its moving to the right (by moving to the left). It’s a little counterintuitive to think about it but basically we are setting the current position of the background to the start of the loading bar. At 0%, it’s the very left of the gradient. At 50%, the middle of the gradient is now at the start of the loading bar (which is on the left). By doing the negative, it would now appear on the right!

The .loading-bar then applies the two keyframes above, with expanding running only once and moving running infinitely with a 1s delay at the start

css
/* This keyframe will create the initial slide animation  */
@keyframes expanding {
    0% {
        transform: scaleX(0);
        opacity: 0;
    }
    100% {
        transform: scaleX(1);
        opacity: 1;
    }
}
 
/* This keyframe will create the loading gradient effect */
@keyframes moving {
    0% {
        background-position: 0 0;
    }
    100% {
        background-position: -200% 0;
    }
}
 
.loading-bar {
    height: 1.25rem;
    transform-origin: left; /* Without this, you'll notice the `expanding` animation starts expanding from the  middle instead of shooting out from the left */
    animation: expanding 0.4s 0.7s forwards linear, moving 1s 1s infinite forwards linear;
    border-radius: 0.125rem;
    background-image: linear-gradient(to right, #eff6ff 30%, #2563eb60 60%, #eff6ff);
    background-size: 200% auto;
    opacity: 0; /* The `expanding` animation will fade in the loading bar */
    animation-delay: 100ms;
}
html
<div class="loading-bar"></div>

Now TailwindCSS!

In your tailwind config, add this:

tailwind.config.js
const config = {
    // .... other configs
    theme: {
        extend: {
            // .... other configs
            keyframes: {
                expanding: {
                    "0%": { transform: "scaleX(0)", opacity: "0" },
                    "100%": { transform: "scaleX(1)", opacity: "100%" },
                },
                moving: {
                    "0%": { backgroundPosition: "0 0" },
                    "100%": { backgroundPosition: "-200% 0" },
                },
            },
            animation: {
                loading: "expanding 0.4s 0.7s forwards linear, moving 1s 1s infinite forwards linear",
            },
        },
    },
};
loading-bar
<!-- Only one loading bar demo  -->
<div
    className="h-5 w-3/5 origin-left animate-loading rounded-sm bg-gradient-to-r from-blue-50 from-40% via-blue-500/60 to-blue-50 to-70% bg-[length:200%] opacity-0"
></div>

The example above I created looks likes this if you want to copy in tailwindcss

loading-bar
<div class="flex h-32 gap-4 p-5 fade-in-25 md:gap-6">
    <div class="size-9 shrink-0 rounded-full bg-gray-100"></div>
    <div class="flex w-full max-w-3xl flex-col gap-4 rounded-lg pt-2">
        <div
            class="h-5 w-10/12 origin-left animate-loading bg-[length:200%] rounded-sm bg-gradient-to-r from-blue-50 from-30% via-blue-600/60 to-blue-50 bg-2x opacity-0"
        ></div>
        <div
            class="h-5 w-full origin-left animate-loading bg-[length:200%] rounded-sm bg-gradient-to-r from-blue-500/60 via-slate-100 via-30% to-blue-500/60 to-60% bg-2x opacity-0 "
        ></div>
        <div
            class="duration-600 h-5 w-3/5 origin-left animate-loading bg-[length:200%] rounded-sm bg-gradient-to-r from-blue-50 from-40% via-blue-500/60 to-blue-50 to-70% bg-2x opacity-0 "
        ></div>
    </div>
</div>

Copyright 2024 Weibo Zhang ©️