iOS 디바이스 에서 body 스크롤을 막는 방법
2 min read
iOS 디바이스에서 body의 스크롤을 완벽하게 막기 위한 시행착오와 방법을 설명하려합니다.
일주일 정도 삽질한 끝에 효과적인 솔루션을 찾았습니다. 😂
배경
iOS Sarafi 에서는
body { overflow: hidden; }
로 body의 스크롤이 막히지 않습니다.
그렇기 때문에 다른 방법을 시도해야만 했습니다.
시도한 방법
검색해서 찾아보니 주로 body-scroll-lock
을 많이들 사용하시는데, 치명적 단점이 존재했습니다.
import { disableBodyScroll } from 'body-scroll-lock'; const Component = () => { const disableScroll = () => disableBodyScroll(document.querySelector('.modal')); return ( <div className="modal"> <span>This is Content.</span> <div className="scroll" style={{ overflow: 'auto' }}> <p>Scroll is not working</p> </div> </div> ); };
위와 같이 disableBodyScroll
의 인자로 넘긴 요소는 스크롤이 잘 되는데
그 하위 요소인 .scroll
요소는 스크롤이 되지 않는 것이었습니다.
결국 해당 라이브러리를 사용할 수 없었고, 다른 방법을 찾았습니다.
해결 방법
방법 | 결과 |
---|---|
touch-move: none; | 동작하지 않음. |
pointer-events: none; | 동작하지 않음. |
body.addEventListener('touchmove', (e) => e.preventDefault()); | 모달 내부 요소도 스크롤이 안됨. |
npm body-scroll-lock | 인자로 넘긴 element의 하위요소는 스크롤 안됨. |
position: fixed; | 정상 작동함. |
해결한 방법은 body에 position: fixed;
를 주는 것이었습니다.
// 스크롤 잠금 const enableScrollLock = () => { const { body } = document; if (!body.getAttribute('scrollY')) { const pageY = window.pageYOffset; body.setAttribute('scrollY', pageY.toString()); body.style.overflow = 'hidden'; body.style.position = 'fixed'; body.style.left = '0px'; body.style.right = '0px'; body.style.bottom = '0px'; body.style.top = `-${pageY}px`; } }; // 스크롤 잠금 해제 const disableScrollLock = () => { const { body } = document; if (body.getAttribute('scrollY')) { body.style.removeProperty('overflow'); body.style.removeProperty('position'); body.style.removeProperty('top'); body.style.removeProperty('left'); body.style.removeProperty('right'); body.style.removeProperty('bottom'); window.scrollTo(0, Number(body.getAttribute('scrollY'))); body.removeAttribute('scrollY'); } };
body 요소를 fixed로 고정되면서 스크롤을 막습니다.
여기서 중요한 포인트는 top 을 -window.pageYOffset
만큼 줘서 fixed로 변경하였지만 변경하지 않은 것 처럼 보이게 하는 것입니다.
스크롤 잠금을 해제할 때는 fixed가 풀리면서 스크롤이 상단으로 이동되는데, window.scrollTo
를 통해 바로 스크롤을 내려주면 자연스럽게 스크롤을 잠그고 해제가 가능합니다.
주의사항
body 에 position: fixed
를 주고 top 으로 강제로 위로 올려버리기 때문에 다른 요소에 position: fixed
가
있지만 top이나 bottom 속성을 주지 않으면 body와 함께 top: -window.pageYOffset
만큼 올라가버립니다.
그렇기 때문에 다른 fixed 요소에 top 혹은 bottom이 있는지 확인 후 수정하시면 되겠습니다!