← Volver a la LecciΓ³n

🎯 Intersection Observer for Animation Triggers

Scroll Events 0
Intersections 0
Animated Cards 0

Why We Need JavaScript Triggers

CSS animations are powerful, but they don't know when to start. An animation that starts immediately when the page loads is wasted if the element isn't visible yet. This demo compares different approaches to triggering animations at the right time.

❌ The Problem: Animations Without Triggers

These cards animate immediately on page load, even though you can't see them yet. By the time you scroll here, the animation has already finished!

⚑

Immediate Start

This animation started as soon as the page loaded, wasting the effect.

🚫

Already Done

You probably missed this animation entirely because it finished before you scrolled here.

⏱️

Poor Timing

Without triggers, animations happen at the wrong time and don't enhance UX.

/* ❌ This starts immediately - bad UX */
.feature-card {
  opacity: 0;
  animation: fadeInUp 0.8s ease-out forwards;
}

/* Animation runs even when element is off-screen */

βœ… The Solution: Intersection Observer API

These cards use Intersection Observer to animate only when they enter the viewport. Scroll down to see them animate at the perfect moment! (They'll glow green while being observed)

🎯

Momento Perfecto

This animates exactly when it becomes visible, creating the best user experience.

⚑

Eficiente

Intersection Observer is efficient and doesn't block the main thread.

🎨

Efecto Escalonado

Notice how cards animate in sequence for a polished, professional feel.

/* βœ… Cards start invisible */
.feature-card {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.8s ease-out, transform 0.8s ease-out;
}

/* JS adds this class when visible */
.feature-card.animate-in {
  opacity: 1;
  transform: translateY(0);
}
// βœ… Intersection Observer setup
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const delay = entry.target.dataset.delay || 0;
      setTimeout(() => {
        entry.target.classList.add('animate-in');
      }, delay);
      observer.unobserve(entry.target); // Stop observing after animation
    }
  });
}, { threshold: 0.2 }); // Trigger when 20% visible

document.querySelectorAll('.observe-me').forEach(card => {
  observer.observe(card);
});

More Examples

πŸ“±

Mobile Friendly

Works perfectly on touch devices without draining battery.

β™Ώ

Accessible

Respects prefers-reduced-motion and provides instant fallbacks.

πŸ”§

Configurable

Adjust thresholds, delays, and root margins easily.

Intersection Observer vs Scroll Listeners

βœ… Intersection Observer (Modern)

  • Fires only when visibility changes
  • Doesn't block main thread
  • Battery efficient
  • Built-in threshold detection
  • Works with lazy loading
  • Easy to debug and maintain

❌ Scroll Listeners (Legacy)

  • Fires 100+ times per second
  • Causes layout thrashing
  • Drains battery quickly
  • Requires manual calculations
  • Complex debouncing needed
  • Difficult to optimize

Notice in the stats at the top: Intersection callbacks fire only when needed, while scroll events fire constantly. This demo tracks both to show the dramatic difference.

πŸŽ“ Puntos Clave