Определение первого прокручиваемого родителя div в JS

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Приведенная ниже функция в JavaScript позволяет выявить ближайший родительский элемент, поддерживающий прокрутку:

JS
Скопировать код
function getScrollableParent(node) {
    let isScrollable = node => /^(auto|scroll)$/.test(window.getComputedStyle(node)['overflow-y']);
    while (node && node !== document.body && !isScrollable(node)) {
        node = node.parentElement; // Движемся к родительскому элементу!
    }
    return node || document.body; // Возвращаем родителя с прокруткой или, при его отсутствии, document.body.
}

const scrollableParent = getScrollableParent(element);

element вам следует заменить на тот элемент, для которого вас интересует первый прокручиваемый родитель. Если таковой не будет обнаружен, функция вернёт document.body.

Кинга Идем в IT: пошаговый план для смены профессии

Заглянем внутрь функции

Рассмотрим подробнее, как функция определяет прокручиваемый родительский элемент.

Определение возможности прокрутки по CSS-свойствам

Функция исследует значение свойства overflow-y в вычисленных стилях каждого элемента. Если оно равно 'auto' или 'scroll', значит элемент поддерживает вертикальную прокрутку.

Подъем вверх по структуре DOM

Функция переходит от одного родительского элемента к другому, используя node.parentElement. Это похоже на взбирание по лестнице структуры DOM.

document.body как альтернатива

Если в процессе такого «взбирания» не обнаружено родительских элементов с поддержкой прокрутки, функция возвращает document.body. Этот элемент всегда способен функционировать как контейнер с прокруткой, особенно при использовании фиксированных позиционирований.

Улучшение решения с помощью некоторых расширений

Обработка изменения ориентации

Нужно учесть, что при макете сайта, адаптивном к размеру экрана, изменение ориентации может влиять на элемент прокрутки. Такое изменение можно улавливать через обработку события resize:

JS
Скопировать код
window.addEventListener('resize', function() {
    // Обработчик ресайза улавливает изменения ориентации экрана.
    const scrollableParent = getScrollableParent(element);
});

Таким образом, при изменении размера окна, функция вновь определит родительский прокручиваемый элемент.

Поддержка прокрутки по обеим осям

Нужно учесть и возможность горизонтальной прокрутки, и, следовательно, расширить условие проверки:

JS
Скопировать код
const isScrollable = n => 
  /^(auto|scroll|overlay)$/.test(window.getComputedStyle(n).overflowY) || 
  /^(auto|scroll|overlay)$/.test(window.getComputedStyle(n).overflowX);

Рефакторинг с использованием ES6

Современный синтаксис поможет улучшить читабельность кода и облегчить его поддержку:

JS
Скопировать код
const getScrollableParent = (node) => {
  const { body } = document;
  const isScrollable = ({ overflowY, overflowX }) => 
    /^(auto|scroll|overlay)$/.test(overflowY) || /^(auto|scroll|overlay)$/.test(overflowX);
  
  while (node && node !== body && !isScrollable(window.getComputedStyle(node))) {
    node = node.parentElement;
  }
  
  return node || body; // Функция вернёт или найденное тело, или разультат выполения выражения, следующего за OR.
};

Визуализация

Можно представить процесс поиска первого прокручиваемого родителя как исследование: функция проверяет каждый элемент на некоторой высоте иерархии на способность скрывать более большой объем содержимого, чем отображает.

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

Полезные материалы

  1. Метод Element.scrollIntoView() – Web API | MDN — здесь можно узнать подробнее о механизме прокрутки к выбранному элементу.
  2. Создание кнопки "Вернуться в начало страницы" — инструкция о том, как реализовать функционал возврата к началу страницы.
  3. overflow – CSS | MDN — работа с CSS-свойством overflow, с использованием которого можно управлять прокруткой страницы.
  4. Современное оформление полос прокрутки в CSS (Update 2022) | CSS-Tricks — обзор современных методов стилизации скроллбаров.
  5. Метод EventTarget.addEventListener() – Web API | MDN — как работать с событиями прокрутки.
  6. Определение размеров элемента – Web API | MDN — о том, как определить размеры элемента, что важно для управления прокруткой.