Skip to content

Instantly share code, notes, and snippets.

@JezDriver
Last active March 25, 2025 05:44
Show Gist options
  • Select an option

  • Save JezDriver/c61487588cb58070c062d5cf76afe5d2 to your computer and use it in GitHub Desktop.

Select an option

Save JezDriver/c61487588cb58070c062d5cf76afe5d2 to your computer and use it in GitHub Desktop.
Peekaboo - animate elements when they enter the viewport #js #css #scss
[data-peekaboo="fadeinup"] {
transition: 1.5s ease;
transition-property: opacity, transform;
// Animations runs automatically if there's no JS
&:not(.visible, html.no-js *) {
opacity: 0;
transform: translateY(1em);
}
}
// We can add more reusable animations
[data-peekaboo="example"] {
// ...
}
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<script>
// Detect JS
document.documentElement.classList.remove('no-js');
document.documentElement.classList.add('has-js');
</script>
</head>
<body>
<h1 data-peekaboo="fadeinup">Heading here</h1>
</body>
</html>
/**
* Watch for elements entering viewport
*
* Thanks to:
* - https://gomakethings.com/how-to-detect-when-an-element-enters-or-leaves-the-viewport-with-vanilla-javascript/
* - https://www.debugbear.com/blog/lazy-load-background-images-intersection-observer
*/
function setupPeekaboo() {
// Get all elements
const peekabooEls = document.querySelectorAll('[data-peekaboo]');
// Create a new IntersectionObserver object
let observer = new IntersectionObserver(function (entries, observer) {
for (let entry of entries) {
// console.log(entry);
if (entry.isIntersecting == true) {
// Add visible class
entry.target.classList.add('visible');
// Stop observing
observer.unobserve(entry.target);
}
}
},
{
threshold: "0.5" // half of element must be in viewport
}
);
// Observe each element
for (let element of peekabooEls) {
observer.observe(element);
}
}
document.addEventListener('DOMContentLoaded', function () {
setupPeekaboo();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment