JSFiddle - React, Tailwind, and code Playground
by Bryan Braun
HTML
<header class="margin-line"></header>
<div class="spacer"></div>
<div class="triangle"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="controls">
<dl>
<dt>Observer top margin:</dt>
<dd id="margin-readout"></dd>
<br />
<dt>Last intersection position:</dt>
<dd id="intersection-readout"></dd>
</dl>
<form action="">
<input id="range" type="range" min="0" max="100" value="50">
</form>
</div>
CSS
.margin-line {
position: fixed;
top: 50px;
width: 100%;
border: 1px solid teal;
}
.spacer {
width: 100%;
height: 300px;
background: antiquewhite;
}
.triangle {
width: 0;
height: 0;
margin: 0 auto;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 16px solid red;
}
.controls {
padding: 8px;
background: #e8e8e8;
display: inline-block;
position: fixed;
left: 0;
bottom: 0;
border: 1px solid #bbb;
font-family: helvetica, ariel, sans-serif;
font-size: 11px;
}
dt,
dd {
display: inline;
}
JavaScript
// Elements
const marginLineEl = document.querySelector('.margin-line');
const rangeEl = document.querySelector('[type="range"]');
const marginReadoutEl = document.querySelector('#margin-readout');
const intersectionReadoutEl = document.querySelector('#intersection-readout');
const triangleEl = document.querySelector('.triangle');
const initialTopMargin = 50;
let observer;
// INTERSECTION OBSERVER CODE
function setupObserver(topMargin) {
const options = {
root: null, // defaults to the viewport
rootMargin: `-${topMargin}px 0px 0px 0px`,
threshold: 1,
}
observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
intersectionReadoutEl.innerHTML = entry.boundingClientRect.top;
});
}, options);
observer.observe(triangleEl);
// Adjust Readout
marginReadoutEl.innerHTML = topMargin;
marginLineEl.style.top = `${event.target.value}px`;
}
setupObserver(initialTopMargin);
// SLIDER CODE
rangeEl.addEventListener('input', (event) => {
observer.unobserve(triangleEl);
setupObserver(event.target.value);
});