export function getScrollParent(el?: HTMLElement, includeHidden = false) {
while (el) {
if (includeHidden ? isPotentiallyScrollable(el) : hasScrollbar(el)) return el
el = el.parentElement!
}
return document.scrollingElement as HTMLElement
}
export function getScrollParents(el?: Element | null, stopAt?: Element | null) {
const elements: HTMLElement[] = []
if (stopAt && el && !stopAt.contains(el)) return elements
while (el) {
if (hasScrollbar(el)) elements.push(el as HTMLElement)
if (el === stopAt) break
el = el.parentElement!
}
return elements
}
export function hasScrollbar(el?: Element | null) {
if (!el || el.nodeType !== Node.ELEMENT_NODE) return false
const style = window.getComputedStyle(el)
return style.overflowY === 'scroll' || (style.overflowY === 'auto' && el.scrollHeight > el.clientHeight)
}
function isPotentiallyScrollable(el?: Element | null) {
if (!el || el.nodeType !== Node.ELEMENT_NODE) return false
const style = window.getComputedStyle(el)
return ['scroll', 'auto'].includes(style.overflowY)
}
export function getScrollBarWidth() {
const outer = document.createElement('div');
outer.style.overflow = 'scroll';
outer.style.height = '200px';
outer.style.width = '100px';
outer.style.position = 'fixed'
outer.style.opacity = '0'
outer.style.pointerEvents = 'none'
document.body.appendChild(outer);
const inner = document.createElement('div');
inner.style.width = '100%';
outer.appendChild(inner);
const widthNoScroll = outer.offsetWidth;
const widthWithScroll = inner.offsetWidth;
outer.remove()
return widthNoScroll - widthWithScroll;
}