DOM Manipulation and Browser APIsLesson 5.4
The Intersection Observer and Mutation Observer APIs
IntersectionObserver, threshold, rootMargin, lazy loading pattern, MutationObserver, observing DOM changes, childList subtree, disconnecting observers, performance vs event listeners
Observing Without Polling
Browser Observer APIs let you react to changes without polling loops or scroll event handlers that fire on every pixel. They are designed for efficiency — callbacks are batched and run outside the main thread where possible.
IntersectionObserver — Detect Element Visibility
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
observer.unobserve(entry.target); // stop watching after reveal
}
});
}, {
threshold: 0.2, // 20% visible triggers callback
rootMargin: "0px 0px -50px 0px" // shrink effective viewport
});
document.querySelectorAll(".reveal").forEach(el => observer.observe(el));
MutationObserver — Watch DOM Changes
const mutObs = new MutationObserver((mutations) => {
mutations.forEach(m => {
m.addedNodes.forEach(node => console.log("Added:", node));
});
});
mutObs.observe(document.querySelector("#feed"), {
childList: true, // watch direct children
subtree: true // include all descendants
});
mutObs.disconnect(); // always clean up when done
Performance and Cleanup
IntersectionObserver is far more efficient than a scroll listener — it runs asynchronously and is batched by the browser. Always call unobserve or disconnect when finished observing. Failing to do so creates memory leaks because the observer holds a reference to every observed element, keeping them alive in memory.
