<main class="scroll-container">
	<section data-index="1">
		<h2>Section 1</h2>
	</section>
	<section data-index="2">
		<h2>Section 2</h2>
	</section>
	<section data-index="3">
		<h2>Section 3</h2>
	</section>
	<section data-index="4">
		<h2>Section 4</h2>
	</section>
</main>
* {
	box-sizing: border-box;
}

body {
	margin: 0;
	font-family: 'Helvetica', sans-serif;
}

.scroll-container {
	height: 100vh;
	overflow-y: scroll;
}

section {
	height: 100vh;
	padding: 1rem;
	display: flex;
	align-items: center;
	justify-content: center;
	background-color: darkorchid;
}

section h2 {
	opacity: 0;
	transition: opacity 5000ms;
}

section.is-visible h2 {
	opacity: 1;
}

section:nth-child(2n) {
	background-color: turquoise;
}

section:nth-child(3n) {
	background-color: tomato;
}
const sections = [...document.querySelectorAll("section")];

let options = {
  rootMargin: "0px",
  threshold: 0.25
};

const callback = (entries, observer) => {
  entries.forEach(entry => {
		const { target } = entry;
		console.log(entry, target)
		
		if (entry.intersectionRatio >= 0.25) {
			target.classList.add("is-visible");
		} else {
			target.classList.remove("is-visible");
		}
  });
};

const observer = new IntersectionObserver(callback, options);

sections.forEach((section, index) => {
  observer.observe(section);
});

window.onload(removeClass());

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.