간단하게 TypeScript + React + Webpack 구성하기
레이어 팝업 시, 팝업은 스크롤이 되고 부모는 스크롤 되지 않게 하기
2018-07-23
Explanation
최근에 안드로이드 앱의 웹 뷰 페이지를 만들던 중 레이어 팝업을 사용할 일이 있었는데, 레이어 팝업 내부에서는 스크롤이 가능하고 부모는 스크롤되지 않게 하던 중에.. 겪은 시행 착오와 해결에 대해 정리해 보려합니다.
우선 간단하게 상황을 테스트 할수 있는 예시 마크업 입니다. 팝업이 뜨고 팝업의 스크롤이 끝나면 부모의 스크롤이 시작됩니다. 여기서 원하는 상황은 팝업의 스크롤이 끝나도 부모(배경)의 스크롤은 되지 않게 하는 것 입니다.
흔하게 가장 간단하게 사용하는 방법은 팝업이 뜰때 ‘body’에 css ‘oveflow’ 값을 ‘hidden’ 으로 주는 방법입니다.
하지만 이 방법은 조금만 검색해 보아도, 좋은 밥법이 아니라는 글이 많습니다. 그리고 무엇보다도 안드로이드 웹 뷰에서는 스크롤을 움직이다보면 화면이 어긋나며 누가 봐도 문제가 있는 화면을 보이며.. 전체적으로 부모의 화면 이동이 발생합니다.
그 다음으로 생각한 방법이 팝업이 뜨기 전에 스크롤의 위치를 기억하고 있다가 팝업이 뜬 후에는 스크롤 이벤트에 팝업이 뜨기 전의 위치로 지속적으로 셋 해주는 방법입니다.
그럴듯한 방법이었지만.. 이 방법 역시 안드로이드 웹 뷰의 환경에서는 스크롤에 대한 이벤트를 웹 뷰와 안드로이드가 함께 받기 때문인지, 최종적으로는 부모의 스크롤 위치가 팝업이 떳을때의 위치로 돌아오기는 하지만 지속적으로 부모의 스크롤이 움직이는 문제가 생깁니다.
그 다음으로 생각한 방법은 팝업이 떳을때에는 스크롤 이벤트(안드로이드 웹뷰에서 사용하였기 때문에 또는 touchmove)를 ‘event.preventDefault’ 메서드를 사용해서 스크롤(터치무브) 이벤트를 막아버리고 팝업 영역 내의 touchmove의 방향과 이동거리를 계산해서 스크롤 효과를 만드는 방법이었는데, UX적으로 잘 만들려면 터치 무브의 속도를 계산해서 스크롤의 가속도까지 구현해야 하기 때문에..
(이건 마지막 방법으로 남겨두었습니다.)
JSFiddle은 예를 위해 너무 정리 없이 작성해서 대략 중요한 부분만 다시 정리해 보면 아래와 같습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<html> <body> <div id="popup"> <div id="popup-content"> ... </div> </div> <div id="page-content"> <div> ... </div> </div> </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
html, body, #page-content { height: 100%; overflow: auto; } #popup { position: fixed; top: 0; left: 0; width: 100%; height: 100%; } #popup-content { height: 100%; overflow: scroll; } |
대략 ‘static’이 아닌 ‘position’ 값을 가지고 있는 ‘#popup’ 레이어는 기본적으로 상위의 우선순위를 가지고 있습니다. 그런데 ‘#popup’의 스크롤이 끝난 후 그 밖의 스크롤이 실행되는 이유는 그 밖의 영역이 더 많은 높이의 영역을 가지고 있기 때문입니다. (아래의 그림이 이해에 도움이 될지 모르겠지만…)
해서 위에 수정한 CSS는 기존의 ‘#popup’ 영역 바깥의 영역의 높이 값을 100%로 디바이스(브라우저) 높이와 같게 설정하고 ‘overflow’ 설정을 ‘auto’로 주어 ‘#popup’의 영역보다 더 큰 영역을 갖을 수 없도록 하여 스크롤이 영향을 받지 않도록 한 것입니다.
조금 더 적어보자면.. 전에는 ‘body’가 컨테이너의 역할로 document의 높이 값을 가지고 있어서 ‘#popup’ 영역 외에서도 스크롤이 발생하는 것이고, 수정 후에는 ‘#page-content’의 영역을 디바이스의 높이로 하는 컨테이너 역할을 하게 되어 ‘#popup’ 이상의 영역을 갖지 않아 스크롤이 생기지 않습니다.