Intersection Observer — это встроенный в современные
браузеры API, позволяющий отслеживать пересечение элементов с областью
видимости (viewport) или другим родительским элементом. Он используется
для ленивой загрузки изображений, анимаций при прокрутке, бесконечной
подгрузки контента и других сценариев, где нужно реагировать на
появление элемента на экране.
Основная идея заключается в том, что вместо постоянной проверки
позиции элемента через события scroll и вычисления
getBoundingClientRect(), браузер сам уведомляет о
пересечении элементов, что значительно повышает производительность.
const observer = new IntersectionObserver(callback, options);
callback — функция, которая вызывается каждый раз,
когда наблюдаемый элемент пересекает область видимости. Она получает
массив объектов IntersectionObserverEntry.options — объект с настройками наблюдения.const options = {
root: null, // наблюдаем относительно viewport
rootMargin: '0px', // отступы от корневого элемента
threshold: 0.5 // процент пересечения, при котором срабатывает callback
};
threshold может быть числом от 0 до 1 или массивом чисел
[0, 0.25, 0.5, 0.75, 1], определяющим на каких долях
видимости элемента должен срабатывать callback.
Для реализации эффектов, аналогичных AOS,
Intersection Observer позволяет запускать анимацию при
появлении элемента на экране.
const elements = document.querySelectorAll('.animate-on-scroll');
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if(entry.isIntersecting){
entry.target.classList.add('animated');
observer.unobserve(entry.target); // Останавливаем наблюдение после анимации
}
});
}, { threshold: 0.1 });
elements.forEach(el => observer.observe(el));
.animate-on-scroll — элементы, которые должны
анимироваться..animated — CSS-класс с нужной анимацией (например,
через @keyframes).Использование observer.unobserve() после срабатывания
позволяет оптимизировать производительность, так как элемент больше не
отслеживается.
root определяет элемент, относительно которого
отслеживается видимость. Если указать null, наблюдение
ведется относительно viewport.
rootMargin позволяет расширить или сузить область
видимости:
const observer = new IntersectionObserver(callback, {
root: null,
rootMargin: '0px 0px -50px 0px', // нижний отступ
threshold: 0.1
});
В этом примере элемент считается пересекающим область видимости, когда он приблизительно на 50px выше низа экрана.
Это полезно для запуска анимаций чуть раньше, чем элемент полностью войдет в видимую область.
Для визуального эффекта достаточно добавить классы с ключевыми кадрами:
.animate-on-scroll {
opacity: 0;
transform: translateY(50px);
transition: all 0.6s ease-out;
}
.animate-on-scroll.animated {
opacity: 1;
transform: translateY(0);
}
Такой подход позволяет добиться плавного появления элементов снизу при скролле, аналогичного библиотеке AOS.
Можно создавать несколько наблюдателей для разных эффектов:
const fadeInObserver = new IntersectionObserver(callback, { threshold: 0.2 });
const slideInObserver = new IntersectionObserver(callback, { threshold: 0.5 });
document.querySelectorAll('.fade-in').forEach(el => fadeInObserver.observe(el));
document.querySelectorAll('.slide-in').forEach(el => slideInObserver.observe(el));
Каждый элемент получает индивидуальные настройки, что позволяет реализовать сложные анимационные схемы без использования сторонних библиотек.
unobserve для элементов после завершения анимации, иначе
при большом количестве элементов производительность может
снизиться.threshold
позволяет запускать разные стадии анимации в зависимости от степени
видимости элемента.observer.observe(newElement) после
добавления элемента в DOM.entry.isIntersecting === false.const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if(entry.isIntersecting){
entry.target.classList.add('visible');
} else {
entry.target.classList.remove('visible');
}
});
}, { threshold: 0.1 });
Такой подход позволяет реализовать интерактивные эффекты, когда элементы появляются и исчезают в зависимости от прокрутки.
Intersection Observer поддерживается во всех
современных браузерах.scroll, так как работает на уровне движка браузера и не
вызывает лишние перерасчеты layout.scroll, но с меньшей эффективностью.Использование этого API позволяет создавать анимации, аналогичные AOS, полностью нативно, с минимальной зависимостью от сторонних библиотек и высокой отзывчивостью интерфейса.