Skip to content

Instantly share code, notes, and snippets.

@guillermodlpa
Last active February 1, 2023 14:21
Show Gist options
  • Save guillermodlpa/30dc3d5bfabc65050fdf80ff8b12d216 to your computer and use it in GitHub Desktop.
Save guillermodlpa/30dc3d5bfabc65050fdf80ff8b12d216 to your computer and use it in GitHub Desktop.
useParallax React effect to add parallax effect to any element easily
import { MutableRefObject, useEffect, useState } from "react";
function useInViewport(ref: MutableRefObject<HTMLElement>) {
const [inViewport, setInViewport] = useState(false);
useEffect(() => {
if (!ref.current) {
return;
}
const callback: IntersectionObserverCallback = (entries, observer) => {
entries.forEach((entry) => {
setInViewport(entry.isIntersecting);
});
};
const observer = new IntersectionObserver(callback, {
root: null, // viewport
rootMargin: "0px",
threshold: 0,
});
observer.observe(ref.current);
return function cleanUp() {
observer.disconnect();
};
}, [ref]);
return inViewport;
}
export default function useParallax(
stableRef: MutableRefObject<HTMLElement>,
transformedRef: MutableRefObject<HTMLElement>,
factor = 10
) {
const inViewport = useInViewport(stableRef);
useEffect(() => {
if (!inViewport) {
return;
}
function handle() {
if (!stableRef.current || !transformedRef.current) {
return;
}
const viewportSize = window.innerHeight;
const { top, height } = stableRef.current.getBoundingClientRect();
const offset = top + height / 2 - viewportSize / 2;
transformedRef.current.style.transform = `translateY(${Math.round(
-offset / factor
)}px)`;
}
window.addEventListener("scroll", handle);
return function cleanUp() {
window.removeEventListener("scroll", handle);
};
}, [inViewport, stableRef, transformedRef, factor]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment