Skip to content

Instantly share code, notes, and snippets.

@markusand
Last active January 21, 2021 13:40
Show Gist options
  • Save markusand/4f82c98645b9b88b242a978bee0c65e4 to your computer and use it in GitHub Desktop.
Save markusand/4f82c98645b9b88b242a978bee0c65e4 to your computer and use it in GitHub Desktop.
Vue.js directive to show (or animate) elements when scrolled
.scroll-show {
opacity: 0;
transition: all 0.5s ease-in-out;
}
.scroll-show-enter { opacity: 1; }
const throttle = (callback, interval) => {
let time = Date.now();
return () => {
if (Date.now() - time > interval) {
callback();
time = Date.now();
}
};
};
export default {
bind(el, bindings) {
const {
target,
delay = 250,
interval = 250,
classname = 'scroll-show',
} = bindings.value || {};
const { stagger } = bindings.modifiers;
const items = target ? [...el.querySelectorAll(target)] : [...el.children];
items.forEach(item => item.classList.add(classname));
el.check = () => { /* eslint-disable-line no-param-reassign */
const { top, bottom } = el.getBoundingClientRect();
let queueItem = 0;
items.forEach((item) => {
const bbox = item.getBoundingClientRect();
const inContainer = !(bbox.top > bottom || bbox.bottom < top);
if (inContainer && !item.classList.contains(`${classname}-enter`)) {
const itemDelay = stagger ? delay * queueItem : 0;
setTimeout(() => item.classList.add(`${classname}-enter`), itemDelay);
queueItem += 1;
}
});
};
el.addEventListener('scroll', throttle(el.check, interval));
},
unbind(el) { el.removeEventListener('scroll', el.check); },
inserted(el) { el.check(); },
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment