CSS Z-Index 설명: 스태킹 혼란을 멈추고 레이어를 프로처럼 관리하기
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-index를 auto가 아닌 값으로 설정했을 때만 생성되는 것이 아니라, 다음과 같은 여러 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‑비트 부호 있는 정수)까지 지원합니다. 매우 큰 숫자를 사용하는 것은 권장되지 않으며, 대신 상대적인 순서를 활용하세요.