CSS Z-Index 설명: 스태킹 혼란을 멈추고 레이어를 프로처럼 관리하기

발행: (2025년 12월 16일 오후 03:55 GMT+9)
8 min read
원문: Dev.to

Source: Dev.to

헤더 위에 드롭다운 메뉴를 놓아보거나, 모든 것 뒤에 고집스럽게 나타나는 모달과 싸워본 적이 있다면, CSS z-index의 혼란스러운 세계를 경험했을 것입니다. 간단해 보이죠—위에 놓으려면 더 큰 숫자를 선택하면 되겠죠?—하지만 갑자기 짜증나게도 작동을 멈춥니다. 이 가이드는 z-index가 실제로 무엇인지, 왜 그렇게 동작하는지, 그리고 대규모 프로젝트에서도 자신 있게 관리할 수 있는 전문가 전략을 공유합니다.

Z‑Index란, 실제로 무엇인가?

Technically, z-index controls the stacking order of positioned elements along the z‑axis (the imaginary line coming out of your screen toward you). A higher z-index value means the element is closer to the user.

Important catch: z-index only works on elements that are positioned—i.e., have position: absolute, relative, fixed, or sticky. It also works on flex items. Applying z-index to a statically positioned element (the default) does nothing.

모두가 가장 흔히 틀리는 #1 사실: 스태킹 컨텍스트

새로운 스태킹 컨텍스트를 만들면 규칙이 바뀝니다. 요소가 스태킹 컨텍스트를 생성하면, 그 자식들의 z-index 값은 해당 컨텍스트 안에만 포함됩니다; 자식들은 서로 경쟁할 수는 있지만, 부모 밖의 요소와는 경쟁할 수 없습니다.

새로운 스태킹 컨텍스트가 생성되는 방법

스태킹 컨텍스트는 위치가 지정된 요소에 z-indexauto가 아닌 값으로 설정했을 때만 생성되는 것이 아니라, 다음과 같은 여러 CSS 속성에 의해서도 예기치 않게 생성됩니다:

  • opacity가 1보다 작을 때
  • 어떤 transform이든 적용될 때 (예: translate, scale, rotate)
  • filter, mix-blend-mode, isolation
  • 특정 flex 및 grid 설정

이것이 고전적인 궁금증을 설명합니다: “왜 z-index: 9999인 내 자식 요소가 z-index: 5인 다른 요소 뒤에 있는 걸까?” 답은 보통 그 자식 요소의 부모가 더 낮은 실제 스태킹 순서를 가진 스태킹 컨텍스트를 만들었기 때문입니다.

실제 사례: 갇힌 툴팁

(부모 요소가 스태킹 컨텍스트를 형성하여 툴팁이 숨겨지는 경우에 대한 코드나 설명을 삽입하세요.)

Z‑Index 관리 전문 실무

로컬 vs. 글로벌 규칙

  • Local: 단일 컴포넌트 내에서 레이어링 (예: 버튼 아이콘을 배경 위에 올리기, 카드의 그림자를 다음 카드 위에 올리기). z-index: 1 같은 작은 값을 사용하고, 컴포넌트 루트에 새로운 스태킹 컨텍스트를 만들어 포함합니다:

    .component {
      position: relative;
      z-index: 0; /* 로컬 스태킹 컨텍스트 생성 */
    }
  • Global: 페이지 전체에서 주요 UI 요소들이 서로 상호작용해야 하는 경우의 레이어링 (예: 헤더, 모달, 드롭다운, 사이드바, 알림). 이러한 값들을 하나의 중앙 위치에서 관리합니다.

글로벌 Z‑Index 스케일 중앙화

CSS 변수(또는 전처리기)를 사용해 모든 글로벌 레이어를 하나의 파일에 정의합니다.

:root {
  --z-index-header:          100;
  --z-index-dropdown:        200;
  --z-index-modal-overlay:  300;
  --z-index-modal:           400;
  --z-index-notification:   500;
  --z-index-tooltip:        600;
}

100부터 시작하면 심리적·실용적 버퍼를 확보할 수 있습니다. 100 이하의 값은 로컬 스태킹에 사용해 충돌을 걱정하지 않아도 됩니다.

논리적이고 유지보수 가능한 시스템 사용

100씩 증가시키는(또는 다른 편안한 간격) 방식은 충분한 여유(99개의 슬롯!)를 제공해 새로운 글로벌 레이어를 추가할 때 전체를 리팩터링하지 않아도 됩니다. 예를 들어, 드롭다운과 모달 사이에 새로운 “사이드바” 레이어를 넣고 싶다면 250을 사용할 수 있습니다.

핵심 요점: 절대값 자체는 중요하지 않으며, 상대적인 순서가 중요합니다. z-index: 2는 항상 z-index: 1보다 위에, z-index: 3보다 아래에 위치합니다, 숫자가 얼마나 크든 상관없이.

실제 사용 사례 및 코드 스니펫

고정 헤더와 그림자

.site-header {
  position: fixed;
  top: 0;
  width: 100%;
  z-index: var(--z-index-header); /* 100 */
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

모달 대화상자

/* Overlay – sits just below the modal */
.modal-overlay {
  position: fixed;
  inset: 0;               /* shorthand for top/right/bottom/left: 0 */
  background: rgba(0,0,0,0.5);
  z-index: var(--z-index-modal-overlay); /* 300 */
}

/* Modal content – must be above the overlay */
.modal-content {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: var(--z-index-modal); /* 400 */
}

드롭다운 메뉴 (로컬 컨텍스트)

.nav-item {
  position: relative;   /* positioning reference */
  z-index: 0;            /* creates a new stacking context */
}

.dropdown {
  position: absolute;
  top: 100%;
  z-index: 1;            /* competes only inside .nav-item */
}

FAQ: 당신의 불타는 Z‑Index 질문들, 답변

Q: 음수 z-index 값을 사용할 수 있나요?
A: 예, 단지 포지셔닝된 요소에만 가능합니다. 음수 값은 요소를 해당 스태킹 컨텍스트의 배경 뒤로 배치하며, 포인터 이벤트에 접근할 수 없게 될 수 있습니다.

Q: 실제로 몇 개의 z-index 레이어가 필요할까요?
A: UI가 요구하는 만큼이면 되지만, 규모를 논리적으로 유지하고 문서화하세요. 임의의 숫자를 과도하게 사용하면 유지보수가 어려워집니다.

Q: z-index의 최대값이나 최소값은 무엇인가요?
A: 사양에서는 z-index를 정수로 정의합니다. 실제로 브라우저는 최소 ‑2,147,483,648부터 최대 2,147,483,647(32‑비트 부호 있는 정수)까지 지원합니다. 매우 큰 숫자를 사용하는 것은 권장되지 않으며, 대신 상대적인 순서를 활용하세요.

Back to Blog

관련 글

더 보기 »