Contents

z-index가 동작하지 않는 경우

popover 등의 컴포넌트를 개발하다 보면 특정 html 엘리먼트를 다른 엘리먼트 위에 표시하고 싶을 때가 있다.

그럴 때 간편하게 사용할 수 있는 것이 css의 z-index 속성이다.

z-index

https://developer.mozilla.org/ko/docs/Web/CSS/z-index

z-index를 지정함으로써 두 가지 항목을 지정할 수 있다.

  1. 현재 쌓임 맥락에서 자신의 위치
  2. 자신에 대한 쌓임 맥락 생성 여부

값 지정

z-index 속성은 auto 키워드 또는 정수 값을 부여함으로써 지정할 수 있다.

  • auto로 지정할 경우, 해당 박스가 새로운 쌓임 맥락을 생성하지 않는다.
    • 즉 현재 쌓임 맥락에서의 위치는 부모 엘리먼트와 동일하다 (위에 표시되지 않는다)
  • 값을 정수로 지정할 경우, 현재 쌓임 맥락에서의 위치로 해당 값을 사용한다.
    • 또한 자신 만의 쌓임 맥락을 생성하고, 해당 맥락에서 자신의 위치를 0으로 설정한다.
    • 이는 현재 엘리먼트의 자식 엘리먼트들의 z-index를 자신 외의 바깥 요소와 비교하여 영향을 미치는 일을 없애기 위해서이다.

보다 복잡한 쌓임 맥락에 대한 이해를 위해서는 아래 공식 문서를 참고해보면 좋다. https://developer.mozilla.org/ko/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index

z-index가 동작하지 않는 몇 가지 이유들

https://coder-coder.com/z-index-isnt-working/

앞서 간단하게 언급만 하고 지나갔던 쌓임 맥락이 생각보다 복잡하게 동작하기 때문에, z-index를 999999와 같은 숫자로 설정한다고 항상 엘리먼트가 최상단에 위치하는 것은 아니다.

1. 동일한 쌓임 맥락에 있는 요소들은 appearance 순서에 영향을 받는다.

z-index 속성을 지정하지 않을 경우에는 웹 페이지의 natural한 쌓임 순서를 따른다. 즉 엘리먼트들의 z-index가 지정되지 않은 경우 엘리먼트들의 appearance 순서에 따라 쌓임 순서를 가지게 된다.

마크업 상 나중에 등장하게 되는 엘리먼트들은 이전에 등장했던 엘리먼트보다 순서 상 위에 위치하게 된다.

2. 엘리먼트들의 position 설정 여부

css position 속성이 정해져 있는지 여부에 따라 쌓임 순서가 정해지기도 한다. static position 값 보다는 relative, absolute와 같은 값으로 설정하는 것이 엘리먼트들의 위치를 고정시키기에는 더 좋다.

position이 정해진 엘리먼트들은 항상 정해져 있지 않은 엘리먼트보다 더 위에 보이게 된다.

때문에 하나의 엘리먼트를 position: relative로 설정해 놓고, 나머지 엘리먼트들은 unpositioned 상태로 두게 한다면 relative한 엘리먼트가 다른 엘리먼트보다 위에 보이게 된다.

3. opacity나 transform 적용 여부

흔히 하는 실수 중 하나가, transform이나 opacity는 단일 엘리먼트에 대한 속성이기 때문에 쌓임 순서에 영향을 미치지 않을 것이라는 것이다.

하지만 transform이나 opacity를 설정하는 것은 엘리먼트들을 새로운 쌓임 맥락에 집어넣겠다는 의미와도 같다.

즉 특정 엘리먼트에 transform 속성을 지정한다는 것은 z-indexposition을 지정하지 않았음에도 불구하고 z-index를 0으로 지정한다는 의미와 동일하다.

해결 방법

그렇다면 popover나 툴팁과 같은 엘리먼트들은 항상 최상단에 위치해야 할텐데, 어떻게 하면 좋을까?

쌓임 맥락간의 간섭을 사전에 방지하고 올바른 z-index 설정을 먹이고 싶다면 최대한 동일한 컨텍스트 안에서 z-index 속성을 설정하는 것을 권고한다.

만약 한 엘리먼트가 position: relative 속성이 설정되어 있고, 다른 엘리먼트는 unpositioned 상태에서 z-index 설정을 해야 한다면 나머지 엘리먼트들도 position: relative 속성을 추가해줘야 한다는 의미이다.

4. 낮은 쌓임 맥락에 있는 엘리먼트는 부모의 z-index 레벨을 따른다

웹 페이지 본문에서 모달 창을 띄우는데, footer나 header가 더 위로 위치하게 되어서 배경이 딤드되지 않는 경험을 겪어본 사람들이 적지는 않을 것이라 예상해본다.

자식 엘리먼트들은 부모의 엘리먼트들의 쌓임 맥락에 제한 받기 때문이다.

예를 들어..

<section class="content">
    <div class="modal"></div>
</section>

<div class="side-tab"></div>

위와 같은 마크업이 있다고 가정해보자.

  • 컨텐츠와 사이드 탭 엘리먼트들은 친척 관계이다 (depth가 동일)
    • 즉 마크업 상에서 동일한 레벨에 위치해 있고, 이는 z-index level과는 다르다.
  • 모달이 컨텐츠 엘리먼트 안에 위치해 있기 때문에, 모달에 적용된 z-index 속성은 부모 엘리먼트 컨텍스트 안에서만 의미 있고 content 엘리먼트에는 영향을 끼치지 않는다.
    • 즉 content 다른 자식 엘리먼트들이 있었다면 모달은 그 엘리먼트 위에 보이게 된다.
    • 하지만 부모 엘리먼트 바깥에 위치한 side-tab에는 영향을 전혀 미치지 못하므로, 딤드되는 듯한 효과를 줄 수 없다 (z-index) 속성이 적용되지 않는다

해결 방법

모달과 같이 컨텐츠 컨텍스트 안에서 논리적으로 가장 위에 위치해 있어야 하는 엘리먼트들은 마크업의 최상위 레벨로 이동시키면 된다.

즉 z-index 레벨은 최상위 컨텍스트의 엘리먼트들끼리 비교 연산을 거치게 되고, 다른 엘리먼트들에 비해 z-index가 높다면 해당 엘리먼트는 무조건 최상위에 위치하게 된다. (올바르게 설정했다면)

또 다른 해결 방법으로는, 컨텐츠에서 position 속성을 제거해서 모달의 z-index 속성을 제한하지 않도록 하는 방법도 있다.

  • 부모 엘리먼트의 position 속성이 지정되어 있지 않다면 자식 엘리먼트의 z-index 속성은 한 단계 상위의 엘리먼트에 적용된다.
  • 하지만 컨텐츠 엘리먼트의 position을 다시 지정해야 할 일이 생긴다면 모달의 순서가 다시 돌아갈 것이기 때문이다.

요약

만약 z-index 속성이 예상처럼 잘 먹히지 않는다면,

  1. 엘리먼트들의 position 속성을 확인하고, z-index 속성이 올바른 순서로 지정되었는지 확인해야 한다.
  2. 부모 엘리먼트들이 자식 엘리먼트들의 z-index 속성을 제한하는 일이 없도록 해야 한다.

즉 popover 라이브러리 등을 사용해서 popover를 개발했는데, 만약 최상단에 위치해야 할 gnb나 lnb보다 위에 위치하게 되어서 이를 가린다면

  • popover의 쌓임 맥락이 다른 엘리먼트들과 비교하였을 때 적절한 hierarchy에 위치해 있는지 확인한다. (자식 엘리먼트의 쌓임 맥락은 부모 엘리먼트의 쌓임 맥락 내에서 적용되기 때문이다)
  • 동일한 쌓임 맥락의 엘리먼트들의 position 속성을 조정한다.