donghakim.dev — zsh
← ls ../blog

툴팁이 잘리면 툴팁이 아니라 조상의 overflow 를 본다

recharts 의 allowEscapeViewBox 와 overflow-x: auto, 두 경우 모두 조상의 클리핑 컨텍스트가 원인이었습니다

note · cover image

툴팁 일부가 화면 끝에서 잘려 보이면 툴팁의 크기나 위치가 아니라 조상 컨테이너의 클리핑 컨텍스트를 먼저 봅니다. DOM 상 툴팁이 그 컨테이너 안에 있으면 컨테이너 밖으로 나간 부분은 무조건 잘립니다. 어드민에서 이 원인으로 두 번 났습니다.

렌더 방식에 따라 취약 여부가 갈립니다.

툴팁조상 overflow 영향이유
MUI Tooltip / Popper없음portal 로 body 에 붙습니다
recharts <Tooltip>기본값이면 없음차트 wrapper 안의 div 인데, 기본은 뷰박스 안으로 위치를 반전시킵니다
순수 CSS 말풍선있음조상 클리핑을 그대로 받습니다

allowEscapeViewBox 를 켜면 recharts 의 방어가 풀립니다

allowEscapeViewBox={{ x: true }} 는 "차트 뷰박스 밖으로 나가도 된다" 는 뜻이고, 그 순간 recharts 의 자동 반전이 꺼집니다. 바깥 MUI Cardoverflow: hidden 이라 나간 만큼 잘립니다.

// 오른쪽 끝 데이터 포인트에서 툴팁 오른쪽이 Card 경계에서 잘립니다
<Tooltip content={<CustomTooltip />} allowEscapeViewBox={{ x: true, y: false }} />

// 기본값이면 커서 오른쪽에 자리가 없을 때 왼쪽으로 반전됩니다
<Tooltip content={<CustomTooltip />} />

기본값이 { x: false, y: false } 라 prop 자체를 지우는 게 맞습니다. 차트보다 넓은 툴팁이 아니면 escape 를 켤 이유가 없습니다.


overflow-x: auto 는 세로도 자릅니다

CSS 규칙상 한 축을 visible 이 아닌 값으로 두면 다른 축의 visibleauto 로 계산됩니다. 가로 스크롤만 원했는데 세로도 클리핑 컨텍스트가 됩니다.

.rankScroll { overflow-x: auto; }   /* overflow-y 도 auto 로 계산됩니다 */

이 컨테이너 안의 표 헤더에서 위로 열리는 말풍선이 컨테이너 맨 위에 걸려 첫 줄이 잘렸습니다. 2560x1233 에서 9개 중 5개가, 19~59px 씩 잘렸습니다.

헤더 말풍선만 아래로 열도록 바꿔 해결했습니다. 아래쪽은 14행짜리 표 안쪽이라 어느 열에서도 잘리지 않습니다.


고를 때

  1. 잘릴 여지가 있으면 MUI Tooltip 처럼 portal 로 붙는 걸 씁니다. 가장 안전합니다.
  2. recharts 툴팁은 기본 위치 로직에 맡깁니다. escape 를 켜야 한다면 조상 중에 overflow 를 가진 게 없는지 같이 확인합니다.
  3. CSS 말풍선은 여는 방향을 컨테이너 안쪽으로 잡습니다. 조상에 overflow: visible 을 되돌리는 방식은 스크롤 동작을 깨므로 마지막 수단입니다.
#css#mui#react#recharts#ux