[React/CSS] 모달창이 열려있을 때 body 스크롤 방지하기

suno·2023년 2월 10일
3
post-thumbnail

구현하고자 하는 것

모달창이 열려있을 때 body 스크롤 방지하기

구현 결과


1️⃣ 첫 번째 시도

  • useEffect를 사용하여 컴포넌트 마운트/언마운트 시 스타일을 지정한다.
  • body의 overflow: hidden으로 지정해서, 스크롤바를 숨긴다.
// components/login/LoginModal.tsx

useEffect(() => {
  document.body.style.overflow = 'hidden';
  return () => {
    document.body.style.overflow = 'unset';
  };
}, []);

👎 스크롤바 자체가 사라지면서, 스크롤바의 너비만큼(16px 정도) 윈도우 내부 사이즈가 변한다.


2️⃣ 두 번째 시도

  • 모달창이 열리면 (컴포넌트가 마운트 되면), body의 위치를 고정한다.
    overflow: scroll 이므로 스크롤바가 사라지지 않는다.
  • 모달창이 닫히면 (컴포넌트가 언마운트 되면), body의 스타일을 해제하고 초기 위치로 스크롤한다.
// utils/modal.ts

/**
 * 스크롤을 방지하고 현재 위치를 반환한다.
 * @returns {number} 현재 스크롤 위치
 */
export const preventScroll = () => {
  const currentScrollY = window.scrollY;
  document.body.style.position = 'fixed';
  document.body.style.width = '100%';
  document.body.style.top = `-${currentScrollY}px`; // 현재 스크롤 위치
  document.body.style.overflowY = 'scroll';
  return currentScrollY;
};

/**
 * 스크롤을 허용하고, 스크롤 방지 함수에서 반환된 위치로 이동한다.
 * @param prevScrollY 스크롤 방지 함수에서 반환된 스크롤 위치
 */
export const allowScroll = (prevScrollY: number) => {
  document.body.style.position = '';
  document.body.style.width = '';
  document.body.style.top = '';
  document.body.style.overflowY = '';
  window.scrollTo(0, prevScrollY);
};
// components/login/LoginModal.tsx

useEffect(() => {
  const prevScrollY = preventScroll();
  return () => {
    allowScroll(prevScrollY);
  };
}, []);

✅ 스크롤바가 사라지지 않고, body의 위치를 고정함으로써 스크롤을 방지한다.


Reference

React에서 Modal 구현하기(feat. createPortal, 스크롤 막기)
[Web Study - CSS]모달창 스크롤 막기

profile
Software Engineer 🍊

1개의 댓글

comment-user-thumbnail
2023년 7월 14일

효진님!! 우연히 보게되어 반가웠어요!!
잘 보고 갑니다 :)

답글 달기