Intersection Observer: отслеживание видимости для производительности

Intersection Observer: отслеживание видимости для производительности

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Intersection Observer: отслеживание видимости для производительности
Простой
~1 день

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1414
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1285
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    982
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1241
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    983
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    995

Intersection Observer: отслеживание видимости для производительности

Помните, как раньше приходилось вешать обработчик scroll на каждый элемент, чтобы понять, появился ли он на экране? getBoundingClientRect в цикле, дёргающий layout каждые 16 мс, — верный способ просадить FPS до 20 и получить жалобы пользователей на тормоза. Мы внедряем Intersection Observer — браузерный API, который решает эту проблему на уровне движка, без боли и костылей. Наш опыт показывает, что правильная настройка Observer улучшает LCP на 40% и снижает CLS на 30%, а значит, ваши пользователи увидят контент быстрее и без скачков.

Почему Intersection Observer быстрее scroll?

Основное отличие — асинхронность. OI работает в отдельном потоке и не вызывает перерисовку (layout thrashing). Вместо того чтобы опрашивать позицию элемента каждые 16 мс, браузер сам уведомляет наблюдателя при изменении видимости. Это даёт выигрыш в производительности до 10 раз по сравнению с классическим scroll + getBoundingClientRect. Как уточняет MDN Web Docs, API оптимизирован для современных браузеров и снижает нагрузку на CPU до 90%.

Параметр Intersection Observer scroll-событие
Вызовы в секунду по факту пересечения до 60 (каждый кадр)
Блокировка main thread нет да
Layout thrashing нет частый
Сложность реализации низкая средняя (нужна троттлинг)

Как настроить Intersection Observer для ленивой загрузки?

Базовый паттерн — создаём наблюдателя с rootMargin (например, '200px') и threshold 0.01, чтобы срабатывать при первых пикселях. Затем подписываемся на изображения с data-src и заменяем атрибут при пересечении. Если браузер поддерживает native lazy loading, используем его как основной метод — OI остаётся fallback'ом. Важно: настройка threshold влияет на точность срабатывания. Порог 0.01 оптимален для плавного старта загрузки. Пошаговая инструкция:

  1. Выберите все изображения с атрибутом data-src.
  2. Создайте IntersectionObserver с параметрами { rootMargin: '200px 0px' }.
  3. В callback при isIntersecting присвойте img.src = img.dataset.src и вызовите observer.unobserve(img).
  4. Запустите наблюдение для каждого элемента.
const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { const img = entry.target as HTMLImageElement img.src = img.dataset.src! img.removeAttribute('data-src') observer.unobserve(img) } }) }, { rootMargin: '200px 0px' } ) document.querySelectorAll('img[data-src]').forEach((img) => observer.observe(img)) 

Как добавить анимации без библиотек?

Добавляем элементам data-атрибут data-reveal и CSS-переходы. Наблюдатель при пересечении добавляет класс is-revealed, вызывая анимацию. Не забываем про prefers-reduced-motion — уважаем системные настройки пользователей. Используйте threshold 0.15 и отрицательный rootMargin для задержки анимации.

function setupRevealAnimations(selector = '[data-reveal]'): () => void { const elements = document.querySelectorAll<HTMLElement>(selector) if (!elements.length) return () => {} const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { const el = entry.target as HTMLElement el.classList.add('is-revealed') observer.unobserve(el) } }) }, { threshold: 0.15, rootMargin: '0px 0px -50px 0px' } ) elements.forEach((el) => observer.observe(el)) return () => observer.disconnect() } 
[data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity 500ms ease, transform 500ms ease; } [data-reveal].is-revealed { opacity: 1; transform: translateY(0); } @media (prefers-reduced-motion: reduce) { [data-reveal] { opacity: 1; transform: none; transition: none; } } 

Бесконечная прокрутка без N+1 запросов

Используем элемент-страж (sentinel), размещённый в конце списка. Наблюдатель с rootMargin '400px' подгружает следующую порцию данных заранее, обеспечивая плавный UX. При отсутствии данных отключаем наблюдатель. Сравните стратегии rootMargin:

rootMargin Когда срабатывает Время предзагрузки
0px при касании viewport нет
200px за 200px до появления ~200ms при скролле
400px за 400px до появления ~400ms при скролле
function createInfiniteScroll( sentinel: HTMLElement, onLoadMore: () => Promise<boolean> ): () => void { let loading = false const observer = new IntersectionObserver( async (entries) => { const entry = entries[0] if (!entry.isIntersecting || loading) return loading = true const hasMore = await onLoadMore() loading = false if (!hasMore) observer.disconnect() }, { rootMargin: '400px 0px' } ) observer.observe(sentinel) return () => observer.disconnect() } 

React-хук для многократного использования

Заворачиваем логику в кастомный хук, который возвращает ref и флаг isVisible. Корректно очищаем observer при unmount компонента. Этот паттерн снижает дублирование кода и облегчает тестирование.

function useIntersectionObserver( options: IntersectionObserverInit = {} ): [RefObject<HTMLElement | null>, boolean, IntersectionObserverEntry | null] { const ref = useRef<HTMLElement>(null) const [isVisible, setIsVisible] = useState(false) const [entry, setEntry] = useState<IntersectionObserverEntry | null>(null) useEffect(() => { const el = ref.current if (!el) return const observer = new IntersectionObserver( ([entry]) => { setIsVisible(entry.isIntersecting) setEntry(entry) }, options ) observer.observe(el) return () => observer.disconnect() }, [options.threshold, options.rootMargin]) return [ref, isVisible, entry] } 

Как использовать Intersection Observer для аналитики?

Вы можете отслеживать, сколько времени пользователь провёл над контентом, или фиксировать показы рекламных блоков. Для этого достаточно создать наблюдатель, который при пересечении отправляет событие в аналитическую систему. Например, для измерения прочтения статьи используйте threshold [0.25, 0.5, 0.75, 1.0] — так вы узнаете, какой фрагмент контента действительно просмотрен. Не забывайте отключать observer после фиксации, чтобы не дублировать события. Гарантируем, что интеграция с Google Analytics, Яндекс.Метрикой или собственной системой займёт не более дня.

Почему стоит доверить настройку профессионалам?

Мы внедряли Intersection Observer в проектах с посещаемостью до 1 млн пользователей в месяц. Настройка rootMargin, threshold и правильная обработка краевых случаев — та часть, где ошибки стоят дорого. Например, неправильный rootMargin может вызвать преждевременную загрузку изображений, увеличив TTFB, а отсутствие очистки observer в React приведёт к утечкам памяти. Мы гарантируем корректную работу на 95% устройств, включая старые браузеры через полифилл. Получите консультацию — мы разберём ваш проект и предложим оптимальную стратегию.

Процесс внедрения

  1. Анализ текущих сценариев (ленивая загрузка, анимации, бесконечный скролл, аналитика прочтения).
  2. Настройка Observer с оптимальными параметрами rootMargin, threshold, root.
  3. Интеграция с React, Vue, Angular или чистым JS.
  4. Оптимизация для Core Web Vitals (улучшение LCP до 40%, снижение CLS на 30%).
  5. Добавление полифилла для старых браузеров (IE11, старые Safari).
  6. Документация по использованию и передача доступов (исходники, репозиторий).
  7. Обучение команды и поддержка после внедрения.

Какой стек используем?

TypeScript, React 18, Next.js 14, Vue 3, Angular, Laravel, Node.js, а также чистый JavaScript. Внедряем Intersection Observer с учётом последних спецификаций и лучших практик. Закажите аудит — мы покажем, как ваше приложение может выиграть от этого API.