[FE] CSS pointer-events 와 이벤트 버블링

쭈리·2024년 3월 27일

FE

목록 보기
8/10

😓 이게 무슨 일이야..

mouseOver 이벤트를 상위 엘리먼트에 줬는데, 하위 엘리멘트에서도 발생해서 엄청난 지진 현상이 발생했다. 정지 버튼 위에 마우스를 가져가면 깜빡이는 현상이 문제이다.

문제의 화면해결 된 화면

처음에는 z-index로 해결할 수 있을까? 했지만 근본적인 해결 방법이 아니었다.

🧐 문제 발견

이벤트에는 이벤트 버블링과 캡처링이라는 현상이 존재한다.

이벤트 버블링 : 요소에서 발생한 이벤트가 해당 요소의 부모 요소로 전파
이벤트 캡처링 : 이벤트가 계층 구조의 최상위 요소에서 시작하여 하위 요소로 전파

자세한 설명은 참고 : 한눈에 이해하는 이벤트 흐름 제어 (버블링 & 캡처링)

내 요소들의 배치는 대략 이렇게 되어있다.

<div css={VideoStyle}>
  <div
    css={ClickZone}
    onClick={playingHandler}
    onMouseOver={hoverHandler}			// 이벤트 발생
    onMouseOut={unhoverHandler}
  />
</div>;
{
  isHover && (
    <div css={PlayBtnStyle}>			// 이벤트 없는데 발생
      <PauseBtn />
    </div>
  );
}

🤔 버블링 확인

같은 div 태그에 쌓인 요소도 아닌데 영향을 받는다고? 라는 생각이 들어서 콘솔로 확인을 해봤다.

// 확인 코드
const hoverHandler = () => {
  setIsHover(() => true);
  console.log('onHover', isHover);
};
  
const unhoverHandler = () => {
  setIsHover(() => false);
  console.log('outHover', isHover);
};

마우스를 일시정지 버튼에 가져가자마자 엄청나게 많은 이벤트가 발생하면서 hover 상태가 변화되는 모습을 볼 수 있었다.

🧐 첫 번째 시도

이벤트 버블링은 하위 요소에 e.stopPropagation()을 추가하면, 상위 요소로 이벤트가 전파되는 것을 막을 수 있다.

const onMouseOver = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
  e.stopPropagation();
  console.log('버블링 확인 : ', e.nativeEvent.bubbles);
}
<div css={PlayBtnStyle} onMouseOver={(e) => checkBubble(e)}>
  <PauseBtn />
</div>
수정 버전
원본

비교가 잘 보이는지 모르겠지만, 정지 버튼을 보면 확실히 적은 오류가 보이는 것을 확인할 수 있다. div에만 e.stopPropagation()을 적용해서 그런지, 원 위에서는 오류가 발생하지 않고 svg에 접근했을 때 발생하는 모습을 볼 수 있다.

하지만 이렇게 일일이 처리해주려면 번거로울 것이다.

여기 아주 간단한 방법이 있다!

😉 pointer-events

css 에 pointer-events라는 속성이 있다. 이 속성은 특정 요소의 트리거 역할을 설정한다. 만약 z-index가 높은 요소 아래에 있는 이벤트를 작동시키고 싶다면, pointer-events : none; 을 적용하면 된다.

const PlayBtnStyle = css`
  pointer-events: none;
`;

비로소 오류 없이 마우스 이벤트가 작동하는 모습을 볼 수 있게 되었다.

📚 배운 내용

이런 상황을 만나면 이벤트 버블링이 왜 필요할까? 라는 생각이 들 수 있지만, 비슷한 요소들 (예를들어 li 태그같은) 에게 한 번에 이벤트를 부여할 수 없다면 굉장히 번거로워질 것이다.
이번 트러블 슈팅 과정을 통해 이벤트 버블링과 캡처링이라는 이벤트 전파 과정을 공부할 수 있었다.

profile
화면 아래에 논리를 펼치는 프론트엔드 엔지니어 🐥

0개의 댓글