Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function getStickyRoot(node: Element) {
- let current = node.parentElement;
- while (current && current !== document.body) {
- const computedStyle = window.getComputedStyle(current);
- const overflow = computedStyle.getPropertyValue('overflow');
- if (overflow === 'scroll' || overflow === 'auto') {
- return current;
- }
- current = current.parentElement;
- }
- return document.body;
- }
- function isNumber(value: any): value is number {
- // the isFinite() check also suffices for !isNaN()
- return typeof value === 'number' && Number.isFinite(value);
- }
- export function stuck(node: Element) {
- const root = getStickyRoot(node);
- function detectStuck() {
- if (getComputedStyle(node).position !== 'sticky') {
- const dirs = ['', 't', 'r', 'b', 'l', 'x', 'y'];
- for (const dir of dirs) {
- const suffix = dir ? `-${dir}` : '';
- node.classList.remove(`stuck${suffix}`);
- }
- }
- const rect = node.getBoundingClientRect();
- const rootRect = root.getBoundingClientRect();
- const computedStyle = window.getComputedStyle(node);
- const top = parseFloat(computedStyle.getPropertyValue('top'));
- const right = parseFloat(computedStyle.getPropertyValue('right'));
- const bottom = parseFloat(computedStyle.getPropertyValue('bottom'));
- const left = parseFloat(computedStyle.getPropertyValue('left'));
- const t = isNumber(top) && rect.top - rootRect.top === top;
- const r = isNumber(right) && rootRect.right - rect.right === right;
- const b = isNumber(bottom) && rootRect.bottom - rect.bottom === bottom;
- const l = isNumber(left) && rect.left - rootRect.left === left;
- const x = l || r;
- const y = t || b;
- let isStuck: boolean = false;
- for (const [dir, condition] of Object.entries({ t, r, b, l, x, y })) {
- if (condition) {
- node.classList.add(`stuck-${dir}`);
- isStuck = true;
- } else {
- node.classList.remove(`stuck-${dir}`);
- }
- }
- if (isStuck) {
- node.classList.add('stuck');
- } else {
- node.classList.remove('stuck');
- }
- }
- root.addEventListener('scroll', detectStuck, { passive: true });
- window.addEventListener('resize', detectStuck, { passive: true });
- return {
- destroy() {
- root.removeEventListener('scroll', detectStuck);
- window.removeEventListener('resize', detectStuck);
- },
- };
- }
Advertisement