By : manish
Language: javascript
Date Published: 4 days, 3 hours ago
The Intersection Observer API lets you efficiently detect when an element enters or leaves the viewport without costly scroll events. This is ideal for lazy‑loading images, triggering animations, or loading infinite‑scroll content. By observing a target element, you get a callback with its intersection ratio, letting you decide when to act. For lazy loading, swap a placeholder’s src with the real image once the element is about to enter the viewport. For animations, add a class that starts a CSS animation when the element becomes visible. The API works in all modern browsers and can be polyfilled for older ones. Use a rootMargin to start loading slightly before the element is fully visible, improving perceived performance. Remember to disconnect observers when components unmount to avoid memory leaks. This pattern reduces initial page weight, improves Core Web Vitals (especially LCP), and keeps interactions smooth without jank from scroll‑based throttling.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | // hooks/useIntersection.js import { useEffect, useState } from "react"; function useIntersectionObserver(options = {}) { const [entry, setEntry] = useState(null); const [node, setNode] = useState(null); useEffect(() => { if (!node) return; const observer = new IntersectionObserver(([obsEntry]) => { setEntry(obsEntry); }, options); observer.observe(node); return () => observer.disconnect(); }, [node, options]); return [setNode, entry]; } // ImageLazy.jsx – lazy‑load an image when it’s near the viewport import { useIntersectionObserver } from "./hooks/useIntersection"; export default function ImageLazy({ src, alt, placeholder = "/placeholder.png" }) { const [setRef, entry] = useIntersectionObserver({ rootMargin: "200px", // start loading 200px before it’s visible threshold: 0, }); const [loaded, setLoaded] = useState(false); // When the image starts to intersect, load the real src useEffect(() => { if (entry && entry.isIntersecting) { setLoaded(true); } }, [entry]); return ( <div> <img ref={setRef} src={loaded ? src : placeholder} alt={alt} style={{ display: "block", maxWidth: "100%", height: "auto" }} loading="lazy" /> {!loaded && ( <div style={{ width: "100%", paddingTop: "56.25%", // 16:9 placeholder background: "#eee", }} /> )} </div> ); } // FadeInOnScroll.jsx – animate elements as they enter the viewport import { useIntersectionObserver } from "./hooks/useIntersection"; export default function FadeInOnScroll({ children }) { const [setRef, entry] = useIntersectionObserver({ threshold: 0.1, // trigger when 10% visible }); const [visible, setVisible] = useState(false); useEffect(() => { if (entry && entry.isIntersecting) { setVisible(true); } }, [entry]); return ( <div ref={setRef} className={visible ? "fade-in" : ""}> {children} </div> ); } // CSS for the animation (add to your stylesheet) /* .fade-in { opacity: 0; transform: translateY(20px); animation: fadeInUp 0.6s ease-out forwards; } @keyframes fadeInUp { to { opacity: 1; transform: translateY(0); } } */ |