Intersection Observer: отслеживание видимости элемента

Что такое Intersection Observer? 🤔

Intersection Observer — это мощный API браузера, который позволяет отслеживать пересечение (видимость) элементов с их родительским контейнером или viewport. Вместо постоянных вычислений в scroll-событиях, он работает асинхронно и эффективно!

Зачем это нужно?

  • Ленивая загрузка изображений (lazy-load)
  • Бесконечный скролл
  • Анимации при появлении элемента
  • Отслеживание аналитики (например, сколько времени пользователь видел блок)

Как создать наблюдателя? 🛠️

const observer = new IntersectionObserver(callback, options);
  • callback: Функция, которая срабатывает при изменении видимости.
  • options: Объект с настройками (необязательный).

Пример с настройками:

const options = {
  root: null,       // Родительский элемент (null = viewport)
  rootMargin: '0px', // Отступы от root (как в CSS)
  threshold: 0.5    // Порог видимости (0–1)
};

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    console.log(entry.isIntersecting ? 'Виден!' : 'Скрыт!');
  });
}, options);

Разбираем параметры entries 🔍

Каждый entry в колбэке содержит полезные свойства:

Свойство Описание
isIntersecting true, если элемент пересекает root
intersectionRatio Процент видимости (0–1)
target Сам наблюдаемый элемент (DOM-узел)
boundingClientRect Размеры и положение элемента относительно viewport

Практический пример: Ленивая загрузка 🖼️

Допустим, у нас есть страница с кучей изображений. Загружать их все сразу — плохая идея. Вместо этого загрузим только те, которые видны пользователю.

HTML:

<img data-src="image1.jpg" class="lazy" alt="Описание">
<img data-src="image2.jpg" class="lazy" alt="Описание">

JavaScript:

const lazyImages = document.querySelectorAll('.lazy');
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src; // Загружаем изображение
      observer.unobserve(img);   // Прекращаем наблюдение
    }
  });
});

lazyImages.forEach(img => observer.observe(img));

💡 Совет: Для плавности добавьте CSS-переход (transition: opacity 0.3s) и изначально установите opacity: 0 для .lazy.


Анимация при появлении 🎬

Хотите, чтобы элементы «вплывали» при скролле? Легко!

CSS:

.fade-in {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.5s, transform 0.5s;
}

.fade-in.visible {
  opacity: 1;
  transform: translateY(0);
}

JavaScript:

const fadeElements = document.querySelectorAll('.fade-in');
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('visible');
    }
  });
}, { threshold: 0.1 });

fadeElements.forEach(el => observer.observe(el));

Когда НЕ использовать Intersection Observer? ⚠️

  1. Точное позиционирование: Если нужно знать координаты элемента в реальном времени (лучше подойдёт getBoundingClientRect()).
  2. Старые браузеры: Для IE11 потребуется полифил (например, intersection-observer от W3C).
  3. Микроанимации: Для простых эффектов иногда хватит CSS @keyframes.

Итоги 🏁

  • Intersection Observer — это современный и эффективный способ отслеживать видимость элементов.
  • Идеально подходит для ленивой загрузки, анимаций и аналитики.
  • Работает асинхронно, не нагружая основной поток.
  • Гибкие настройки: root, rootMargin, threshold.

Попробуйте применить его в своём следующем проекте — и вы ощутите разницу! 🚀

Скрыть рекламу навсегда

📘 VK Видео — обучение без ограничений

Все уроки доступны без VPN, без блокировок и зависаний.

Можно смотреть с телефона, планшета или компьютера — в любое время.

▶️ Смотреть на VK Видео