Auto Animate

November 10, 2023

AutoAnimate is a fantastic little javascript utility I just stumbled across on Twitter. To quote the AutoAnimate website, "AutoAnimate adds automatic animations to your JavaScript applications with a single line of code.". That's it, super easy to install and super easy to use.

I'm a big fan of simple little micro animations and embellishments to spice up websites so I decided to tinker with it using AlpineJs (another favourite of mine).  After seeing Ian's tweet I knew this was something I needed to checkout. 

Autoanimate tweet


I threw together a simple snack generator that randomly grabs a snack and displays it in a grid. Nothing very exciting and as you can see in the video below, pretty blah when items are added/remove and shuffled. The important thing is that it add/removes DOM elements in a parent which is all AutoAnimate needs to see to make some magic happen. Here's the AlpineJs data class I used"snacks", () => {
   return {
      emojis: [
         {name: 'Hamburger', emoji: '🍔'},
         {name: 'Pizza', emoji: '🍕'},
         {name: 'Taco', emoji: '🌮'},
         {name: 'Salad', emoji: '🥗'},
         {name: 'Sandwich', emoji: '🥪'},
         {name: 'Soup', emoji: '🍲'},
         {name: 'Sushi', emoji: '🍣'},
         {name: 'Spaghetti', emoji: '🍝'},
         {name: 'Chicken', emoji: '🍗'}
      items: [], 
      id: 0,
      shuffle(array) {
         for (let i = array.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [array[i], array[j]] = [array[j], array[i]];
         let idx = Math.floor(Math.random(1)*this.emojis.length);
         this.items.push({name: this.emojis[idx].name, emoji: this.emojis[idx].emoji, id:});
         let idx = this.items.findIndex(element => == id); 

And here's the HTML, notice the `x-animate` attribute on the main DOM element and the DIV that contains all the snacks.

<div class="w-1/2 p-5 border border-black rounded-md " x-data="snacks()" x-animate>
   <div class="flex flex-row justify-between items-center">
      <button class="font-bold border-black border-2 px-4 py-2 rounded-md hover:bg-green-300 transition duration-200 "
         @click="add()">Add A Snack</button>
      <button class="font-bold border-black border-2 px-4 py-2 rounded-md hover:bg-green-300 transition duration-200"
   <template x-if="items.length > 0">
      <div class="grid grid-cols-2 gap-4 mt-5 transition duration-500" x-animate>
         <template x-for="item in items" :key="">
            <div class="relative group flex justify-between">
               <div class="flex items-center gap-5">
                     class="w-20 h-20 relative rounded-full flex items-center justify-center bg-green-200 border border-green-400">
                     <span class="text-4xl" x-text="item.emoji"></span>
                        class=" text-red-500  opacity-0 group-hover:opacity-100 transition duration-200 absolute top-0 left-0 w-full h-full flex items-center justify-center"
                        <svg xmlns="" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
                           stroke="currentColor" class="w-16 h-16">
                           <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
                  <span class="text-2xl" x-text=""></span>


import autoAnimate from "@formkit/auto-animate";
import Alpine from "alpinejs";
window.Alpine = Alpine;
Alpine.directive('animate', el => {autoAnimate(el)});

That's it. Two lines, one to import and one for the new directive. 


Sprinkle in that new AlpineJs directive and an `x-animate` attribute on the list and checkout the results. Pretty crazy upgrade for 2 lines of code. Overall it added 15KB of javascript (4KB gzipped). Completely worth it.

Final word

From the AutoAnimate website:


AutoAnimate is fundamentally a single function — autoAnimate — that accepts a parent element. Automatic animations will be applied to the parent element and its immediate children. Animations are specifically triggered when one of three events occurs:

  • A child is added in the DOM.
  • A child is removed in the DOM.
  • A child is moved in the DOM.


That's really the only thing to keep in mind when mixing it into AlpineJs. It won't work with `x-show` if you are hiding/showing elements, you need to use `x-if` with a `template` so DOM elements are actively being added/removed from some parent element.