Framework/React & RN
[Hooks] 모달 띄웠을 때 스크롤을 막는 방법
Joonfluence
2022. 4. 15. 14:35
오늘은 모달이 떠있는 상태에서 스크롤이 안되도록 처리해보겠습니다. 방법은 아주 간단합니다! 모달을 띄울 때, body의 style로 overflow hidden을 주면 됩니다. 반대로, 모달을 닫을 땐 overflow 속성을 지워주면 되겠죠?
import { useCallback } from 'react';
export function useBodyScrollLock() {
const lockScroll = useCallback(() => {
document.body.style.overflow = 'hidden';
}, []);
const openScroll = useCallback(() => {
document.body.style.removeProperty('overflow');
}, []);
return { lockScroll, openScroll };
}
모달 컴포넌트가 작성되어 있는 상황을 가정해봅시다. 그러면 코드는 아래와 같아지겠죠.
const Component: FC<Props> = ({ label, imageSource }) => {
const [isOpen, setIsOpen] = useState(false);
const { lockScroll, openScroll } = useBodyScrollLock();
const handleOpen = () => {
lockScroll();
setIsOpen(true);
};
const handleClose = () => {
openScroll();
setIsOpen(false);
};
return (
<div>
<div onClick={handleOpen}>
<img
src={imageSource}
alt={label}
></img>
</div>
<span>{label}</span>
{isOpen && (
<Modal
isOpen={isOpen}
handleClose={handleClose}
/>
)}
</div>
);
};
단순하게 위 코드로만 테스트했을 때, IOS Chorome/Safari에선 overflow hidden이 정상적으로 작동되지 않는 문제가 있었습니다. 따라서 스크롤이 되지 않도록 처리하는 코드를 추가해줘야 하는데요. 아래와 같이, position fixed를 주고, top 위치로 사용자가 스크롤한 위치만큼 -로 계산해주는 것입니다. 그러면 overflow 속성 없이도 스크롤을 막아줄 수 있습니다.
import { useCallback } from 'react';
export function useBodyScrollLock() {
let scrollPosition = 0;
const lockScroll = useCallback(() => {
// for IOS safari
scrollPosition = window.pageYOffset;
document.body.style.overflow = 'hidden';
document.body.style.position = 'fixed';
document.body.style.top = `-${scrollPosition}px`;
document.body.style.width = '100%';
}, []);
const openScroll = useCallback(() => {
// for IOS safari
document.body.style.removeProperty('overflow');
document.body.style.removeProperty('position');
document.body.style.removeProperty('top');
document.body.style.removeProperty('width');
window.scrollTo(0, scrollPosition);
}, []);
return { lockScroll, openScroll };
}
이상으로 설명을 마치겠습니다. 읽어주셔서 감사합니다!
반응형