JSFiddle - React, Tailwind, and code Playground
by Chris Ball
HTML
<div id="parent">
<div id="scroller">
<header class="header">
<nav class="nav">
<div class="link">one</div>
<div class="link">two</div>
<div class="link">three</div>
</nav>
</header>
<section></section>
<section class="dark"></section>
<section></section>
<section class="dark"></section>
<section></section>
<section class="dark"></section>
<section></section>
<section class="dark"></section>
<section></section>
<section class="dark"></section>
</div>
</div>
SCSS
$nav-height: 3rem;
* {
font-family: sans-serif;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
overflow: hidden;
}
#parent {
height: 100%;
left: 0;
overflow-y: scroll;
position: absolute;
top: 0;
width: 100%;
}
#scroller {
position: relative;
}
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
.nav {
align-items: center;
border: 1px solid red;
display: flex;
flex-direction: row;
height: $nav-height;
justify-content: center;
padding: 0.5rem;
transition: color 300ms;
width: 100%;
&.dark {
color: #fff;
}
}
.link {
padding: 0 1rem;
}
section {
height: 100vh;
width: 100%;
&.dark {
background: #222;
}
}
JavaScript
let darkSections = document.querySelectorAll('section.dark')
let pageNav = document.querySelector('.nav')
let headerHeight = document.querySelector('.header').offsetHeight
let windowHeight = window.innerHeight
let bottomMargin = windowHeight - headerHeight
// Intersection config
let options = {
root: document.getElementById("parent"),
rootMargin: `0px 0px -${bottomMargin}px 0px`,
threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
}
// Intersection logic
let intersectionObserver = new IntersectionObserver(function(entries) {
entries.forEach(entry => {
if (entry.intersectionRatio > 0.5) {
pageNav.classList.add('dark')
console.log('intersecting :)')
} else {
pageNav.classList.remove('dark')
console.log('NOT intersecting :(')
}
})
}, options)
// Add intersection observers
;[...darkSections].forEach(section => {
intersectionObserver.observe(section)
})