Определение первого прокручиваемого родителя div в JS
Быстрый ответ
Приведенная ниже функция в JavaScript позволяет выявить ближайший родительский элемент, поддерживающий прокрутку:
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
.
Заглянем внутрь функции
Рассмотрим подробнее, как функция определяет прокручиваемый родительский элемент.
Определение возможности прокрутки по CSS-свойствам
Функция исследует значение свойства overflow-y
в вычисленных стилях каждого элемента. Если оно равно 'auto' или 'scroll', значит элемент поддерживает вертикальную прокрутку.
Подъем вверх по структуре DOM
Функция переходит от одного родительского элемента к другому, используя node.parentElement
. Это похоже на взбирание по лестнице структуры DOM.
document.body как альтернатива
Если в процессе такого «взбирания» не обнаружено родительских элементов с поддержкой прокрутки, функция возвращает document.body
. Этот элемент всегда способен функционировать как контейнер с прокруткой, особенно при использовании фиксированных позиционирований.
Улучшение решения с помощью некоторых расширений
Обработка изменения ориентации
Нужно учесть, что при макете сайта, адаптивном к размеру экрана, изменение ориентации может влиять на элемент прокрутки. Такое изменение можно улавливать через обработку события resize:
window.addEventListener('resize', function() {
// Обработчик ресайза улавливает изменения ориентации экрана.
const scrollableParent = getScrollableParent(element);
});
Таким образом, при изменении размера окна, функция вновь определит родительский прокручиваемый элемент.
Поддержка прокрутки по обеим осям
Нужно учесть и возможность горизонтальной прокрутки, и, следовательно, расширить условие проверки:
const isScrollable = n =>
/^(auto|scroll|overlay)$/.test(window.getComputedStyle(n).overflowY) ||
/^(auto|scroll|overlay)$/.test(window.getComputedStyle(n).overflowX);
Рефакторинг с использованием ES6
Современный синтаксис поможет улучшить читабельность кода и облегчить его поддержку:
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.
};
Визуализация
Можно представить процесс поиска первого прокручиваемого родителя как исследование: функция проверяет каждый элемент на некоторой высоте иерархии на способность скрывать более большой объем содержимого, чем отображает.
"Экспедиция" заканчивается, когда обнаруживается родитель, который умеет скрывать часть информации.
Полезные материалы
- Метод Element.scrollIntoView() – Web API | MDN — здесь можно узнать подробнее о механизме прокрутки к выбранному элементу.
- Создание кнопки "Вернуться в начало страницы" — инструкция о том, как реализовать функционал возврата к началу страницы.
- overflow – CSS | MDN — работа с CSS-свойством overflow, с использованием которого можно управлять прокруткой страницы.
- Современное оформление полос прокрутки в CSS (Update 2022) | CSS-Tricks — обзор современных методов стилизации скроллбаров.
- Метод EventTarget.addEventListener() – Web API | MDN — как работать с событиями прокрутки.
- Определение размеров элемента – Web API | MDN — о том, как определить размеры элемента, что важно для управления прокруткой.