Image Trail Effect

Partager

This effect is widely used in modern web design: when the user moves their mouse, a succession of images appears and disappears with a smooth animation.

Add the HTML Structure in Elementor

  1. In Elementor, add an HTML Widget to your page.
  2. Paste this code:
<div class="items"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>

<script>
   const imagePaths = [
      "https://images.pexels.com/photos/18131871/pexels-photo-18131871.jpeg?w=300&auto=compress&cs=tinysrgb",
      "https://images.pexels.com/photos/18398708/pexels-photo-18398708.jpeg?w=300&auto=compress&cs=tinysrgb",
      "https://images.pexels.com/photos/18131896/pexels-photo-18131896.jpeg?w=300&auto=compress&cs=tinysrgb",
      "https://images.pexels.com/photos/18398385/pexels-photo-18398385.jpeg?w=300&auto=compress&cs=tinysrgb",
      "https://images.pexels.com/photos/18398430/pexels-photo-18398430.jpeg?w=300&auto=compress&cs=tinysrgb"
      // ajoute ou enlève des images ici
   ];

   document.addEventListener("DOMContentLoaded", function () {
      const container = document.querySelector(".items");
      let imageIndex = 0;

      let lastX = null;
      let lastY = null;
      const minDistance = 100; // Distance minimale avant apparition d’une nouvelle image

      function getDistance(x1, y1, x2, y2) {
         const dx = x2 - x1;
         const dy = y2 - y1;
         return Math.sqrt(dx * dx + dy * dy);
      }

      function addNewItem(x, y, dx, dy) {
         const newItem = document.createElement("div");
         newItem.className = "item";
         newItem.style.position = "absolute";
         newItem.style.left = `${x - 150}px`;
         newItem.style.top = `${y - 150}px`;
         newItem.style.width = "300px";
         newItem.style.height = "300px"; // définit la taille de l'image
         newItem.style.pointerEvents = "none";

         const img = document.createElement("img");
         img.src = imagePaths[imageIndex];
         img.style.width = "100%";
         img.style.height = "100%";
         img.style.objectFit = "contain";
         newItem.appendChild(img);

         container.appendChild(newItem);

         imageIndex = (imageIndex + 1) % imagePaths.length;

         const randomRotation = gsap.utils.random(0, 0);

         // Normalisation direction
         const length = Math.sqrt(dx * dx + dy * dy) || 1;
         const dirX = (dx / length) * 80; // Direction et amplitude de l’entrée
         const dirY = (dy / length) * 80; // Direction et amplitude de l’entrée

         // Animation GSAP
         gsap.timeline()
            .fromTo(newItem,
               { scale: 1, opacity: 1, rotation: randomRotation, x: -dirX, y: -dirY },
               { scale: 1, opacity: 1, x: 0, y: 0, duration: 0.4, ease: "power2.out" } 
            )
            .to(newItem,
               { 
                 scale: 0.3, opacity: 0, duration: 1, ease: "power2.out", delay: 0.05, 
                 onComplete: () => newItem.remove() 
               } 
            );
      }

      container.addEventListener("mousemove", function (event) {
         if (lastX === null || lastY === null) {
            lastX = event.pageX;
            lastY = event.pageY;
            return;
         }

         const dx = event.pageX - lastX;
         const dy = event.pageY - lastY;
         const distance = getDistance(lastX, lastY, event.pageX, event.pageY);

         if (distance > minDistance) {
            addNewItem(event.pageX, event.pageY, dx, dy);
            lastX = event.pageX;
            lastY = event.pageY;
         }
      });
   });
</script>

Add the CSS in Elementor

Still in the HTML widget, go to Advanced and then Custom CSS, add:

.items { 
  position: fixed; 
  top: 0; 
  left: 0; 
  width: 100vw; 
  height: 100vh; 
  will-change: transform, opacity; 
  z-index: 999; /* passe au-dessus du contenu */
} 

.item { 
  position: absolute; 
  width: 450px; 
  height: 600px; 
  overflow: hidden; 
} 

.item img { 
  width: 150%; 
  height: 250%; 
  object-fit: cover; 
}

Customize the Animation

You can adapt the effect by modifying these key lines of the script:

Minimum distance before a new image appears const minDistance = 100; → Lower = more images, higher = fewer images.

Direction and amplitude of entry const dirX = (dx / length) * 80; const dirY = (dy / length) * 80; → Change 80 to increase/decrease the “trajectory” effect.

Appearance duration duration: 0.4 → Lower = faster, higher = slower.

Disappearance animation
Currently: scale: 0.3, opacity: 0, duration: 1, ease: "power2.out"
Suggested variant for a downward fall effect:

y: window.innerHeight + 300, opacity: 0, scale: 0.3, duration: 1.2, ease: "power2.in", onComplete: () => item.remove()

Practical Tips

  • Image compression: optimize images with TinyPNG or Squoosh.
  • Image size: avoid overly heavy originals (200–400px max for this effect).
  • Mobile performance: disable this effect on mobile if smoothness is not optimal.
Categorie
Compatible
WordPress, Elementor
Mis à jour
17 Sep 2025

Créer avec Elementor

Hébergez, créez et développez le site web de vos rêves avec la première plateforme pour WordPress.

Inspirez vos projets Elementor avec 1 animation par semaine.

Merci de ton inscription !

Créer avec Elementor

Hébergez, créez et développez le site web de vos rêves avec la première plateforme pour WordPress.