Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallTo detect when a page has scrolled past a location, place a small sentinel element at that location and observe it with an IntersectionObserver. With threshold: 0, the observer reports when the sentinel enters or leaves the viewport; use !entry.isIntersecting as the current “past the marker” state. For a fixed header, adjust the trigger line with rootMargin.
Detect a scroll threshold with a sentinel
An IntersectionObserver watches a target element in relation to a root rectangle. Set root: null to use the document viewport, then put a sentinel where the page should change state—for example, immediately before the section at which a sticky header should appear.
Give the sentinel a small height, such as 1 pixel, rather than relying on a zero-sized element. A zero-sized target can make boundary behavior harder to interpret. Test the marker in the page’s actual layout.
<div id="scroll-marker" aria-hidden="true"></div>
<script>
const marker = document.querySelector('#scroll-marker');
const observer = new IntersectionObserver(
([entry]) => {
document.body.classList.toggle('past-marker', !entry.isIntersecting);
},
{
root: null,
threshold: 0
}
);
observer.observe(marker);
</script>
Here, threshold: 0 means the callback responds to crossing the root boundary; it is not a percentage of the page’s scroll distance. The callback sets the class from the sentinel’s current intersection state. MDN explains that isIntersecting is true when the target is at least partly intersecting the root or document.
Adjust the trigger for a fixed header
If a fixed header is 80 pixels tall and the marker should count as passed when it moves behind that header, shrink the top of the observer’s effective root by 80 pixels:
#1 Best Overall
const observer = new IntersectionObserver(
([entry]) => {
setPast(entry.boundingClientRect.top < 0 && !entry.isIntersecting);
},
{
root: null,
rootMargin: '-80px 0px 0px 0px',
threshold: 0
}
);
observer.observe(document.querySelector('#scroll-marker'));
rootMargin offsets the root rectangle before intersection testing. A negative top margin shrinks it from the top, moving the effective trigger line down; a positive margin expands it. Pixel and percentage units are accepted. Use an offset that matches the actual fixed-header height and desired trigger point.
Choose the observer settings for the job
- Viewport or scroll panel: Use
root: nullfor the document viewport. For a scrollable panel, setrootto the panel element; the target must be inside that root. - One boundary or several visibility milestones: A single
threshold: 0is the usual choice for entering or leaving a boundary. Use an array such as[0, 0.5, 1]only if you need callbacks at multiple visibility ratios. - Current state or direction:
entry.isIntersectingdescribes the current intersection state, not whether the user is scrolling down or up. To identify direction, retain previous state or compare the current and previousboundingClientRect.top. - Repeated tracking or one-time action: Keep updating a boolean on each callback if the UI must respond in both directions. For a one-time transition, call
unobserve(marker)after the qualifying crossing.
Keep the observer efficient and clean it up
IntersectionObserver delivers callbacks asynchronously when configured thresholds are crossed, avoiding the need to calculate target geometry in a raw scroll handler for this pattern. The callback still runs on the main thread, so keep it short. When the page or component is destroyed, call disconnect(); if only one target is finished, call unobserve(target).
Rank #2
trackVisibility: true adds checks for occlusion and visual effects. It is computationally intensive, defaults to false, and should be paired with an appropriate delay only when visibility beyond geometric intersection is genuinely required.
Browser support and nested scrolling
MDN marks the core IntersectionObserver API as broadly available across browsers since March 2019. Newer options can have different compatibility. In particular, MDN labels scrollMargin Baseline 2025 and reports support across the latest devices since September 2025, while noting that older devices may not support it. For the common viewport or single-root sentinel pattern, rootMargin is the established offset mechanism; check compatibility before depending on scrollMargin for nested scroll containers.
Quick Recap
Best Value
Rank #4
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

