Intersection Observer
Example of having an element changing from header to ribbon on scroll with intersectionObserver.
by Travis Almand
HTML
<div id="secondary_wrapper">
<div id="secondary">
<div id="profile" class="scrolled"></div>
</div>
</div>
<div id="primary_wrapper">
<div id="primary">
<div id="logo"></div>
<div id="promo"></div>
</div>
</div>
<main></main>
CSS
body,
html {
margin: 0;
padding: 0;
}
#secondary_wrapper {
background-color: gray;
height: 40px;
position: fixed;
width: 100%;
}
#primary_wrapper {
background-color: gainsboro;
}
#secondary {
background-color: gray;
height: 40px;
left: 0;
margin: auto;
position: fixed;
right: 0;
width: 75%;
z-index: 2;
}
#profile {
background-color: rebeccapurple;
height: 40px;
position: absolute;
right: 0;
width: 120px;
z-index: 5;
}
#profile.scrolled {
height: 50px;
}
#primary {
align-items: center;
background-color: gainsboro;
display: flex;
height: 80px;
margin: auto;
padding-top: 40px;
width: 75%;
}
#logo {
border: 1px solid gray;
height: 50px;
width: 120px;
}
#promo {
flex-grow: 1;
}
main {
height: 2000px;
}
JavaScript
console.clear();
var profile = document.querySelector('#profile');
var secondary = document.querySelector('#secondary');
var primary = document.querySelector('#primary');
var top = (primary.offsetHeight - profile.offsetHeight) / 2 + 20;
var callback = function (entries, observer) {
var clientRectY = entries[0].boundingClientRect.y;
profile.classList.toggle('scrolled', clientRectY >= 0);
if (profile.classList.contains('scrolled')) {
profile.style.top = top + 'px';
} else {
profile.style.top = '0px';
}
}
var options = {
root: null,
rootMargin: '0px',
threshold: 1.0
}
var observer = new IntersectionObserver(callback, options);
var target = document.querySelector('#primary');
observer.observe(target);
window.setTimeout(function () {
profile.style.transition = 'all 0.25s';
}, 100);