본문 바로가기

FrontEnd

[CSS][Layout][Relative layout][z-index 관리하기]

반응형

해당 게시물은 https://css-for-js.dev/ 코스를 학습하며 정리한 내용입니다.

사전 지식 : 쌓임 맥락

z-index는 특정 조건에서만 효력이 발생한다.
특히 브라우저의 기본 레이아웃인 Flow Layout 모드에선 효력이 없다.
https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context

Z-index가 관리하기 어려운 이유

내가 언제 어디서 어떤 숫자를 썼더라...?

일반적인 방법 : 높은 Z-index 주기

이미지 위의 텍스트 상자


일반적으로 위와 같이 이미지 위에 카드를 올리고 싶으면, z-index를 주면 된다.
z-index는 z축이다. 클수록 위로 튀어나온다.

<style>
  .wrapper {
    /* Create a containing block */
    position: relative;
  }
  .card {
    position: relative;
    z-index: 2;
  }
  .decoration {
    position: absolute;
    z-index: 1;
  }
</style>
<div class="wrapper">
  <div class="card">
    Hello World
  </div>
  <img
    alt=""
    src="/decorative-blob-1.svg"
    class="decoration"
    style="top: -20px; left: -70px;"
  />
  <img
    alt=""
    src="/decorative-blob-2.svg"
    class="decoration"
    style="top: -50px; left: -10px;"
  />
  <!-- Other blobs omitted for brevity -->
</div>

Relative Layout Mode 요소들은 순서대로 쌓인다.

참고 : 브라우저의 렌더링 순서

  • 먼저 위치가 지정되지 않은 모든 요소가 렌더링됩니다(Flow, Flexbox, Grid...).
  • 다음으로, 위치 지정 요소가 맨 위에 렌더링됩니다 (relative, absolute, fixed, sticky).
  • 브라우저는 각 단계마다 뒤에 나오는 요소를 위에 올립니다.

아래 사항을 고려하면 z-index를 없앨 수 있다.

  • wrapper에는 position:relative를 적용한다.(즉 Relative Layout 모드를 따른다)
  • relative layout 요소끼리 나오는 순서대로 쌓인다.
  • .decoration 클래스 적용 요소는 .wrapper 기준으로 위치한다.

즉, 아래와 같이 바꿀 수 있다.

<style>
  .wrapper {
    position: relative;
  }
  .card {
    position: relative;
  }
  .decoration {
    position: absolute;
  }
</style>

<div class="wrapper">
  <img
    alt=""
    src="/course-materials/decorative-blob-1.svg"
    class="decoration"
    style="top: -20px; left: -70px;"
  />
  <img
    alt=""
    src="/course-materials/decorative-blob-2.svg"
    class="decoration"
    style="top: -50px; left: -10px;"
  />
  <img
    alt=""
    src="/course-materials/decorative-blob-3.svg"
    class="decoration"
    style="bottom: -80px; right: -50px;"
  />
  <img
    alt=""
    src="/course-materials/decorative-blob-4.svg"
    class="decoration"
    style="bottom: 50px; right: -120px;"
  />
  <div class="card">
    Hello World
  </div>
</div>

주의 : Link, Button ,Form, Input 같은 대화형 요소는 돔 순서를 바꾸면 탭 순서가 바뀐다.

쌓임 맥락 격리

아래와 같은 화면이 있었다.

before develop


z-index를 써서 아래와 같이 바꿨다.

after bad develop

<style>
  .card {
    position: relative;
    z-index: 1;
  }
  .primary.card {
    z-index: 2;
  }
</style>
<section class="pricing">
  <article class="card">
    <!-- Stuff omitted -->
  </article>
  <article class="primary card">
    <!-- Stuff omitted -->
  </article>
  <article class="card">
    <!-- Stuff omitted -->
  </article>
</section>

아뿔사! header의 z-index가 2였다.

bug

<style>
  header {
    position: fixed;
    z-index: 2;
  }
  .card {
    position: relative;
    z-index: 1;
  }
  .primary.card {
    z-index: 2;
  }
</style>
<header>Synergistic Inc.</header>
<main>
  <section class="pricing">
    <article class="card">
      <!-- Stuff omitted -->
    </article>
    <article class="primary card">
      <!-- Stuff omitted -->
    </article>
    <article class="card">
      <!-- Stuff omitted -->
    </article>
  </section>
</main>

해당 현상의 원인은 다음과 같다.

1 : header, .card, .primary.card의 쌓임 맥락은 동일 레벨이다. (:root 아래)
2 : header보다 .primar.card가 뒤에 나오므로 위에 쌓인다.

이 문제는, 새로운 쌓임 맥락을 만들어 해결할 수 있다.

계층화된 요소를 쌓임맥락으로 묶어(격리해) z-인덱스 값이 있는 "최상위" 요소의 수를 줄인다.

.pricing {
  position: relative;
  z-index: 1;
}

비유하자면 2 vs 1.2 이렇게 비교하는 효과가 생긴다.
1.2전체 위에 2가 쌓이게 되는 것이다.

isolation property

주의! : 해당 방법은 IE에서 못씀

InternetExplorerIsNotSupportIsolationProperty

z-index의 문제는, 최상위 z-index 사용 요소들 간의 경합이다.
이는 컴포넌트 기반 개발을 하게 되면 더 큰 문제가 된다.
isolation property를 이용하면 z-index없이 쌓임 맥락을 만들 수 있다.

.pricing {
  isolation: isolate;
}

이는 해당 요소가 독립적인 쌓임 맥락을 갖는다는 것을 의미한다.

예제 코드 보기

https://codesandbox.io/s/hardcore-fog-7vex5?file=/index.html

더 많은 자료 보기

https://itchallenger.tistory.com/

반응형