[React] Modal 만들기(2) 외부화면 스크롤 방지하기
https://joylee-developer.tistory.com/184
React에서 Modal 만들기에 대한 글을 작성하다가 글이 길어져서 스크롤 방지에 대한 내용은 따로 글을 작성했다.
3. modal이 떠 있을 땐 화면 스크롤이 금지되어 있다.
스크롤에 대한 설정을 따로 하지 않으면 뒷쪽 화면이 움직일 수 있다.
뒷면이 움직이지 않도록 모달이 떠 있을 땐 스크롤을 금지하고, 모달이 사라지면 가능하도록 설정해주어야 한다.
3-1. CSS로 설정하기
overflow: hidden 설정으로 스크롤을 막을 수 있다.
1
2
3
4
|
useEffect(() => {
document.body.style= `overflow: hidden`;
return () => document.body.style = `overflow: auto`
}, [])
|
cs |
하지만 이 방법의 경우, 스크롤은 막았지만 스크롤바가 사라졌다가 다시 나타나므로 화면의 폭이 바뀌면서 내부 화면도 바뀔 수 있다. 스크롤바가 없는 모바일 화면의 경우는 사용 가능하지만, 스크롤바가 나타나는 데스크탑 페이지의 경우는 적합하지 않다.
1
2
3
4
5
6
7
8
9
10
11
12
|
useEffect(() => {
document.body.style.cssText = `
position: fixed;
top: -${window.scrollY}px;
overflow-y: scroll;
width: 100%;`;
return () => {
const scrollY = document.body.style.top;
document.body.style.cssText = '';
window.scrollTo(0, parseInt(scrollY || '0', 10) * -1);
};
}, []);
|
cs |
body의 position을 고정시켜 스크롤을 막을 수 있다.
이 경우에는 top을 설정해주어야 한다. top이 설정되지 않으면 모달을 열었을 때, 현재 위치가 아닌 최상위 위치로 스크롤이 이동하기 때문이다.
그래서 position: fixed; 설정과 함께 top: -${window.scrollY}px;으로 현재 위치로 스크롤을 이동시키고, 모달이 사라질 때 window.scrollTo(0, parseInt(scrollY || '0', 10) * -1);으로 원래 위치로 이동시켜야 한다.
3-2. eventListener를 사용하는 방법
화면을 움직이는 이벤트에 대해 모두 반응하지 않게 설정한다.
1
2
3
4
5
6
7
8
9
10
11
|
function Modal(props) {
useEffect(() => {
// modal이 떠 있을 땐 스크롤 막음
disableScroll();
// modal 닫히면 다시 스크롤 가능하도록 함
return () => enableScroll();
}, []);
// 생략
}
export default Modal;
|
cs |
useEffect를 사용해 component가 생성될 때 disableScroll이 실행되고, component가 제거될 때 enableScroll이 실행되도록 설정한다.
두 가지 방법 다 사용 가능하므로 원하는 대로 코드를 적용하면 된다.
참고한 사이트
https://im-developer.tistory.com/201
https://velog.io/@do_dadu/React에서-Modal-구현하기feat.-createPortal-스크롤-막기