SeonHyungJo / Tip-Note

:round_pushpin: 개발을 하면서 느끼고 알게된 Tip:round_pushpin:
7 stars 0 forks source link

# Body 스크롤 막기 #77

Open SeonHyungJo opened 3 years ago

SeonHyungJo commented 3 years ago

Body 스크롤 막기

Modal, Popup, Alert를 개발해서 적용하다 보면 이상하게 내가 보는 화면이 스크롤이 되는 것이 아닌 뒤에 영역이 스크롤이 되는 것을 확인할 수 있다.

오늘은 그 스크롤을 한 번 막아보자.

흔하게 일어나는 이슈는 2가지이다.

두 번째의 경우 특히 TouchMove로 작동하는 모바일에서 일어난다.

흔히 막는 방법

우리가 아는 흔한 스크롤을 막는 방법은 많은 블로그에 나와있다.

  overflow: hidden;
  touch-action:none;

위와 같은 방법과 더불어 이벤트 전파를 막아서 안되도록 하는 방법으로 설명하는 곳도 있다.

경험상 위와 같은 방법으로 body에 style을 바로 추가해주면 문제가 발생한다.

1개의 Modal이 떠있는데 Popup, Alert가 나올 수 있다. 이때 닫게 되면 body의 스타일이 사라지게 되어 남아있는 Modal에서 body의 스크롤이 가능하게 된다.

이는 간단하게 해결 가능하다.

SCSS를 사용한다는 가정하게 아래와 같이 정의하면 된다.

.scroll-prevent {
  overflow: hidden;
  touch-action:none;
}

.modal-scroll-prevent {
  @extend .scroll-prevent;
}

.popup-scroll-prevent {
  @extend .scroll-prevent;
}

.alert-scroll-prevent {
  @extend .scroll-prevent;
}

위와 같이 정의를 하고 각각이 나올때 body에 class로 추가를 하고 지워질 때 해당 class만 지워준다면 만족할 수 있다.

모바일에서

overflw를 hidden으로 처리해도 mobile safari에서 modal의 마지막까지 스크롤 이후 body가 스크롤되는 이슈가 발생한다.

이는 한 블로그에서 작성해주신 코드로 해결이 된다.

해당 코드는 React 코드로 스크롤이 일어날때 보이는 영역의 끝자리를 판단해서 반대 방향으로 스크롤하여 영역 외에 부분이 스크롤이 되지 않도록 해준다.

const preventMomentumScroll = useCallback((el) => {
    const {scrollTop, offsetHeight, scrollHeight} = el;
    if (scrollTop === 0) {
      el.scrollTo(0, 1);
      return true;
    }
    if (scrollTop + offsetHeight >= scrollHeight) {
      el.scrollTo(0, scrollHeight - offsetHeight - 1);
      return true;
    }
    return false;
  }, []);