본문 바로가기
Q&A해결2026년 8월 18일1분 읽기

모달 z-index를 9999로 줬는데도 다른 요소 밑에 깔려요

z
zindex_baram
조회 1032댓글 2

페이지에 모달을 띄우는데, 모달이 특정 카드 컴포넌트 밑에 깔려서 반쯤 가려집니다. 당연히 z-index 문제겠거니 하고 모달에 z-index: 9999까지 줬는데도 그대로예요.

모달은 position: fixed고, 문제의 카드는 z-index가 그렇게 높지도 않아요(한 10 정도). 상식적으론 9999가 이겨야 하는데 안 이깁니다. 카드가 들어있는 섹션에 스크롤 등장 애니메이션이 걸려 있어서 부모에 transform이랑 opacity가 들어가 있긴 한데, 이게 관련이 있을까요? z-index를 100000으로 올려봐도 소용없네요.

댓글 2

김김영삼2개월 전
숫자 싸움 문제가 아니라 스택 컨텍스트(stacking context) 문제예요. 그 애니메이션 부모에 걸린 transform이 범인입니다. transform, opacity(1 미만), filter, will-change 같은 속성이 붙은 요소는 새로운 스택 컨텍스트를 만들어요. 그러면 그 안에 있는 자식들의 z-index는 아무리 커도 그 컨텍스트 "내부"에서만 유효하고, 바깥 세계(모달)와는 애초에 같은 무대에서 비교되지 않습니다.

지금 상황이 이래요. 카드의 부모 섹션이 transform 때문에 독립된 스택 컨텍스트가 됐고, 그 섹션 자체가 페이지 흐름상 모달보다 위에 쌓이는 구조가 된 겁니다. 그러면 모달 z-index가 9999든 100000이든, 카드는 그 섹션 컨텍스트에 통째로 얹혀서 모달 위로 올라와버려요. z-index 숫자로는 절대 못 이깁니다. 서로 다른 우주에 있는 거라서요.

제일 확실한 해결은 모달을 그 스택 컨텍스트 바깥, 즉 body 최상단으로 빼는 겁니다. React면 createPortal로 모달을 document.body에 렌더하세요. 그러면 모달이 애니메이션 섹션의 컨텍스트에 갇히지 않고 최상위에서 그려져서 z-index가 정상적으로 먹습니다. 모달/토스트/드롭다운을 포털로 body에 붙이는 게 이런 문제를 원천 차단하는 표준 패턴이에요.

포털을 못 쓰는 상황이면, 애니메이션 부모에서 스택 컨텍스트를 유발하는 속성을 손보는 방향인데, 애니메이션이 끝난 뒤 transform을 none으로 되돌리거나 will-change를 떼주면 컨텍스트가 해제됩니다. 다만 애니메이션이 계속 필요하면 이 방법은 한계가 있어서, 결국 포털이 정답인 경우가 많아요.
zzindex_baram(guest)2개월 전
transform이 스택 컨텍스트를 만든다는 걸 처음 알았어요. createPortal로 모달을 body에 붙이니까 z-index 999만 줘도 깔끔하게 위로 올라옵니다. 숫자만 계속 올리던 제가 바보 같네요 😅 명쾌한 설명 감사합니다!
Ctrl+Enter로 등록