Intersection Observer Generator
Generate production-ready IntersectionObserver code for reveal-on-scroll, lazy-loading, infinite scroll, scroll-spy, sticky headers, video autoplay, and impression tracking — in vanilla JS, a React useInView hook, or Vue 3. Tune threshold and rootMargin with a live trigger-zone diagram.
About this ToolHow it works, benefits & use casesTap to collapse
Configure an IntersectionObserver visually and get production-ready code for seven common patterns. Start by picking a use case — reveal on scroll, lazy-load images, infinite scroll, scroll-spy active nav, sticky-header trigger, video autoplay in view, or impression analytics — and the tool fills in sensible threshold, rootMargin, and "trigger once" defaults for that pattern. From there you fine-tune everything: drag a slider for a single visibility ratio or switch to multiple stops (up to six) for progressive effects, step the top/right/bottom/left rootMargin in pixels, point the observer at a custom scroll root via a CSS selector, and toggle whether each element is unobserved after its first intersection. A live trigger-zone diagram shows the viewport, the dashed effective root after your rootMargin, the target element, and where it crosses the trigger line. Pick a framework — vanilla JS, a typed React useInView hook, or a Vue 3 Composition API single-file component — and the generator emits matching code with proper cleanup, plus companion CSS for the reveal, scroll-spy, and sticky-header patterns and contextual notes about gotchas. The whole configuration is captured in a shareable URL.
How to Use
- 1Pick a use case (reveal, lazy-load, infinite scroll, scroll-spy, sticky header, video autoplay, or impression) to apply its threshold and rootMargin defaults.
- 2Choose an output framework: Vanilla JS, React hook, or Vue 3.
- 3Set the visibility threshold with the slider, or enable "Multiple stops" to add up to six ratios.
- 4Adjust the top/right/bottom/left rootMargin in px, optionally set a custom root selector, and toggle "Trigger once".
- 5Copy, download, or share the generated code (and the companion CSS, when shown).
Key Benefits
- Seven ready use cases each apply tuned threshold, rootMargin, and trigger-once defaults in one click
- Outputs vanilla JS, a typed React useInView hook, or a Vue 3 Composition API component
- Live trigger-zone diagram visualizes the effective root, rootMargin band, and threshold crossing
- Threshold slider plus a multi-stop mode (up to six ratios) for progressive effects
- Per-side rootMargin steppers and an optional custom scroll-root selector
- Generated code always includes cleanup (unobserve / disconnect) and pattern-specific notes
- Companion CSS for reveal, scroll-spy, and sticky-header patterns, and a shareable URL for the whole config
Common Use Cases
- Fading or sliding sections into view on scroll with the reveal pattern and its companion CSS
- Lazy-loading images by swapping data-src just before they enter the viewport
- Triggering an infinite-scroll fetch when a bottom sentinel appears
- Highlighting the active nav link for the section currently on screen with scroll-spy
- Dropping a tested useInView hook or Vue 3 observer component into an existing app
Trigger zone
Dashed box = root after rootMargin: 0px 0px -80px. The callback fires when 15% of the target crosses the dashed trigger line.
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
observer.unobserve(entry.target);
}
});
}, {
root: null, // viewport
rootMargin: '0px 0px -80px',
threshold: 0.15,
});
document.querySelectorAll('.reveal').forEach((el) => observer.observe(el));
.reveal {
opacity: 0;
transform: translateY(24px);
transition: opacity 0.6s ease, transform 0.6s ease;
}
.reveal.is-visible {
opacity: 1;
transform: none;
}
@media (prefers-reduced-motion: reduce) {
.reveal {
transition: none;
}
}Use case
Pick a pattern — defaults for threshold and rootMargin are applied automatically.
Output
CSS selector for a scrollable ancestor. Leave blank to use the browser viewport.
Threshold
Fraction of the element that must be visible before the callback fires (0 = any pixel, 1 = fully visible).
Root margin
Grow (positive) or shrink (negative) the root box on each side, in px. Positive bottom values trigger earlier as you scroll down.
rootMargin: "0px 0px -80px"
Behavior
Stop observing each element after its first intersection. Best for reveals, lazy-load, and impressions.
Notes for reveal on scroll
- `once` is on: each element is unobserved after its first intersection, so the effect never reverses.
- Pair the JS with the reveal CSS so elements start hidden and animate in. Respects prefers-reduced-motion.
- Effective rootMargin: "0px 0px -80px".
Understanding threshold & rootMargin
thresholdis the fraction of the target element that must be visible for the observer's callback to run. 0 fires as soon as a single pixel enters; 1 waits until the element is fully on screen. Pass an array (e.g. [0, 0.5, 1]) to be notified at several visibility stops.
rootMargingrows or shrinks the root's bounding box before intersections are calculated, like CSS margin (top right bottom left). Positive values expand the trigger area so the callback fires earlier; negative values shrink it so it fires later. A positive bottom margin is the classic trick for pre-loading images and infinite-scroll pages before the user reaches them.
Was this tool helpful?
Share Your Experience
Help others discover this tool!
Related tools
- CSS FormatterFormat and beautify CSS code
- TypeScript FormatterFormat and beautify TypeScript code
- cURL to Code ConverterConvert cURL commands to code in various languages
- GraphQL Schema ValidatorValidate GraphQL schema definitions
- OpenAPI Spec ViewerView and explore OpenAPI/Swagger specifications
- Postman to cURL ConverterConvert Postman requests to cURL commands
Three, selectable with the framework toggle. Vanilla JS emits a standalone observer that queries the relevant elements for your use case (e.g. .reveal, img[data-src], or #sentinel). React gives a reusable, generically typed useInView hook returning [ref, inView], plus a usage component tailored to the chosen pattern. Vue 3 gives a Composition API single-file component using onMounted/onBeforeUnmount.
Each of the seven use cases applies its own recommended defaults — threshold, per-side rootMargin, and whether "trigger once" is on — and changes the generated code body. Reveal toggles an is-visible class, lazy-load swaps data-src, infinite scroll calls loadMore on a sentinel, scroll-spy highlights a nav link, sticky-header watches a top sentinel, video autoplay plays/pauses a muted video, and impression fires a tracking event the first time an element is seen.

