Skip to content

Instantly share code, notes, and snippets.

@thomaswilburn
Created February 10, 2016 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thomaswilburn/641d6d7fb5e7ac1ba417 to your computer and use it in GitHub Desktop.
Save thomaswilburn/641d6d7fb5e7ac1ba417 to your computer and use it in GitHub Desktop.
Scroll-triggered effects without jQuery
/*
This causes any elements with scroll-class attributes to add be updated either when they
reach the halfway point of the window, or when a target element (matching the selector in
the scroll-trigger attribute) reaches that point. For example:
<div class="example" scroll-class="activated" scroll-trigger=".trigger">
This element will gain the "activated" class when the following element scrolls halfway:
<span class="trigger">TRIGGER ELEMENT</span>
</div>
All code is written in ES6, meant to be translated via Babel, but it should be easy to follow.
*/
//function that returns an array of matching elements
var $ = s => Array.prototype.slice.call(document.querySelectorAll(s));
//turn the elements into objects with target, area, and className properties
var elements = $("[scroll-class]").map(function(target) {
var area = target.getAttribute("scroll-trigger");
if (area) {
area = document.querySelector(area) || target;
} else {
area = target;
}
var className = target.getAttribute("scroll-class") || "scroll-activated"
return { target, area, className };
});
window.addEventListener("scroll", function() {
elements.forEach(function(scroll) {
var bounds = scroll.area.getBoundingClientRect();
if (bounds.top < window.innerHeight * .5) {
scroll.target.classList.add(scroll.className);
} else {
scroll.target.classList.remove(scroll.className);
}
})
});
/*
General purpose code to be notified when an element enters the viewport.
To be used as such:
var element = document.querySelector(".example");
subscribe(element, subscribe.VISIBLE, function() {
element.classList.add("fade-in");
//return true here to stay subscribed, otherwise the element is removed from further notifications
});
*/
var scrollNotified = [];
var noop = function() {};
var subscribe = function(el, test, callback = noop) {
if (typeof test == "function") {
callback = test;
test = "visible";
}
scrollNotified.push({ el, callback, test });
onScroll();
};
subscribe.VISIBLE = "visible";
subscribe.ENTER = "enter";
subscribe.MIDDLE = "middle";
subscribe.PAST = "past";
var onScroll = function() {
scrollNotified = scrollNotified.filter(function(sub) {
var bounds = sub.el.getBoundingClientRect();
switch (sub.test) {
case subscribe.ENTER:
if (bounds.top > 0 && bounds.top < window.innerHeight) {
return sub.callback();
}
break;
case subscribe.MIDDLE:
if (bounds.top > 0 && bounds.top < window.innerHeight * .5) {
return sub.callback();
}
break;
case subscribe.PAST:
if (bounds.top < window.innerHeight * .5) {
return sub.callback();
}
break;
case subscribe.visible:
default:
if (bounds.top > 0 && bounds.bottom < window.innerHeight) {
return sub.callback();
}
}
return true;
});
};
window.addEventListener("scroll", onScroll);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment