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? ⚠️
- Точное позиционирование: Если нужно знать координаты элемента в реальном времени (лучше подойдёт
getBoundingClientRect()). - Старые браузеры: Для IE11 потребуется полифил (например,
intersection-observerот W3C). - Микроанимации: Для простых эффектов иногда хватит CSS
@keyframes.
Итоги 🏁
- Intersection Observer — это современный и эффективный способ отслеживать видимость элементов.
- Идеально подходит для ленивой загрузки, анимаций и аналитики.
- Работает асинхронно, не нагружая основной поток.
- Гибкие настройки:
root,rootMargin,threshold.
Попробуйте применить его в своём следующем проекте — и вы ощутите разницу! 🚀