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
- In Elementor, add an HTML Widget to your page.
- 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.