Определяем видимость элемента с IntersectionObserver

IntersectionObserver — это новый браузерный API, позволяющий асинхронно следить за степенью пересечения элемента с вьюпортом или другим элементом. С его помощью можно определить, виден ли элемент на экране, если виден, то насколько (целиком или частично), а также когда именно он оказался виден. Пример того, где это может потребоваться — модуль для ленивой загрузки картинок.

Недавно на работе была задача залогировать событие просмотра блока на сайте. Я как представил, что нужно подписываться на событие скролла и вручную считать, входит ли элемент целиком во вьюпорт... А затем вспомнил про IntersectionObserver, прочитал документацию и обрадовался, потому что с ним задача решается гораздо проще и красивее:

const observer = new IntersectionObserver(handleIntersection, {
    root: null, // отслеживаем пересечение с вьюпортом, а не с элементом, поэтому null
    threshold: 1 // порог видимости, при котором сработает обзёрвер; 1 означает полную видимость, 0.5 означало бы 50% видимости
});

observer.observe(document.getElementById('target'));

function handleIntersection(entries) {
    // Обзёрвер срабатывает в том числе когда элемент скрывается из вьюпорта, поэтому нужна дополнительная проверка
    if (entries[0].intersectionRatio === 1) {
        logBlockView();
    }
}

IntersectionObserver поддерживается в последних версиях Chrome, Edge и Firefox, для остальных браузеров есть полифил (6,6 КБ в минифицированном виде). Подробнее об IntersectionObserver на MDN.