JSFiddle - React, Tailwind, and code Playground
by Sub Lines
HTML
<div class="observer__target"></div>
<span class="observer__state">Scroll Down</span>
CSS
body {
margin: 0;
height: 300vh;
}
.observer__target {
position: relative;
width: 80%;
height: 50vh;
margin: 200vh auto;
background: rebeccapurple;
}
.observer__state {
position: fixed;
top: 1em;
left: 1em;
color: #fff;
font: 400 1.125em/1.5 sans-serif;
background: black;
padding: .5em;
}
JavaScript
const state = document.querySelector('.observer__state')
const target = document.querySelector('.observer__target')
const thresholdArray = steps => Array(steps + 1)
.fill(0)
.map((_, index) => index / steps || 0)
let previousY = 0
let previousRatio = 0
const handleIntersect = entries => {
entries.forEach(entry => {
const currentY = entry.boundingClientRect.y
const currentRatio = entry.intersectionRatio
const isIntersecting = entry.isIntersecting
// Scrolling down/up
if (currentY < previousY) {
if (currentRatio > previousRatio && isIntersecting) {
state.textContent ="Scrolling down enter"
} else {
state.textContent ="Scrolling down leave"
}
} else if (currentY > previousY && isIntersecting) {
if (currentRatio < previousRatio) {
state.textContent ="Scrolling up leave"
} else {
state.textContent ="Scrolling up enter"
}
}
previousY = currentY
previousRatio = currentRatio
})
}
const observer = new IntersectionObserver(handleIntersect, {
threshold: thresholdArray(20),
})
observer.observe(target)