
잡코리아 등 웹페이지를 보다보면 오른쪽에 스크롤을 따라 움직이는 div들, 즉 광고들이 보인다.

그 중에서 마켓컬리에서 결제금액이 결제 관련 (쿠폰, 포인트 등)div의 위치부터 움직이는 것이 보였다. 윗 부분에서는 움직이지 않는 div를 움직이도록 하는 것이다.
이를 구현해보고자 했고, 결제하기 페이지를 구성했다.

next.js, 타입스크립트, tailwind, react-hook-useForm ,schad/cn 이용하고 있으며,
아래 코드를 변형한다면 react에도 적용가능함.
참고자료가 많이 없어 고민을 많이 했는데 결국 위의 내용처럼 성공하게 되었다.
다만 이번에는 많은 ref가 필요하지 않았고, 상위 페이지의 제일 바깥 div의 ref도 필요없었다.
그때는 스크롤을 한번 내릴 때 하나씩 화면에 꽉찬 div가 나타났어야 했기 때문에 다른 조건이었다.
//useState를 이용하여 아래 jsx 코드 부분에서 논리 연산자(&&) 이용할 예정
const [IsTotalRef, setIsTotalRef] = useState(false);
//타입스크립트이기 때문에 타입지정
const totalDivRef = useRef<HTMLDivElement | null>(null);
const onScroll = () => {
if (totalDivRef.current) {
//ref가 null이 아닐 때, 특정 디브가 페이지 상단에 닿으면 IsTotalRef를 true로 변경
const totalDivTop = totalDivRef.current.getBoundingClientRect().top;
if (totalDivTop <= 0) {
setIsTotalRef(true);
} else {
setIsTotalRef(false);
}
}
};
//useEffect를 통해 ref가 바뀔 때만 onScroll 함수 적용
useEffect(() => {
onScroll();
window.addEventListener('scroll', onScroll);
//아래 return 문이 스크롤 이벤트가 이용되지 않는 경우
//cleanUp함수 역할을 해서 이벤트가 제거
return () => {
window.removeEventListener('scroll', onScroll);
};
}, [IsTotalRef]);
** getBoundingClientRect() 메서드는 DOMRect요소의 크기와 브라우저 뷰포트에 상대적인 위치에 대한 정보를 제공 하는 객체를 반환함. 위의 경우 dom의 top의 위치를 알려줌.
참고:
https://kyounghwan01.github.io/blog/JS/JSbasic/getBoundingClientRect/#%E1%84%80%E1%85%AE%E1%84%86%E1%85%AE%E1%86%AB
그래서 relative인 상태에서 fixed로 바뀌도록 했고, relative는 다른 상태로도 대체 가능하다.
//바뀔 지점의 div에 ref 지정함
<div ref={totalDivRef}>
<div className="flex border-t-[2px] border-gray-200/15 pt-[50px]">
<div className="grid justify-start justify-items-center w-[742px] pb-[300px]">
//...생략...
<Card
className={cn(
// 현재 next.js tailwind 스타일을 적용중
// IsTotalRef가 false인지 true인지에 따라 삼항연산자에 따라 스타일이 바뀐다.
IsTotalRef
? 'fixed top-[20px] grid w-[300px] border-none'
: 'relative grid w-[300px] border-none',
)}>
//...생략...
</Card>
</div>
