Skip to content
This page has been auto-translated and may contain errors.View in English

포지셔닝과 z-index

docs.scrimba.com

상품 사진의 오른쪽 위 모서리에 작은 "Sale" 배지를 올리고 싶다고 해봅시다. 페이지가 스크롤되어도 헤더는 그 자리에 그대로 있었으면 합니다. 그리고 페이지의 다른 모든 것 위에 떠 있는 대화창도 필요합니다. 일반적인 CSS 여백 조정으로는 이런 걸 할 수 없습니다. 여백은 요소를 그저 순서대로 배치할 뿐이니까요. 포지셔닝은 요소가 그 일반적인 배치 흐름에서 벗어나 여러분이 지정한 정확한 위치에, 심지어 다른 요소 위에도 자리 잡을 수 있게 해주는 도구 모음입니다.

position 속성

모든 요소는 static 포지셔닝 상태로 시작합니다. 쉽게 말해 "페이지 흐름 속 원래 자리에 그대로 있는다"는 뜻입니다. 이게 기본값이고, 대부분의 경우 우리가 원하는 상태이기도 합니다. 포지셔닝이 의미를 갖기 시작하는 시점은 요소를 그 원래 자리에서 벗어나게 하고 싶을 때입니다.

그다음 단계는 position: relative입니다. 이 속성은 top, right, bottom, left라는 네 가지 오프셋 속성을 사용해 요소를 원래 있던 자리에서 살짝 밀어냅니다. 중요한 점은 요소가 원래의 공간을 그대로 유지한다는 것입니다. 다른 요소가 그 빈 공간을 채우러 움직이지 않습니다.

css
.badge {
  position: relative;
  top: 10px;                 /* 원래 자리에서 아래로 10px 밀림 */
  left: 20px;                /* 원래 자리에서 오른쪽으로 20px 밀림 */
}

static 요소에는 top이나 left 오프셋을 줘도 아무 효과가 없습니다. positionstatic이 아닌 값으로 지정해야만 이 오프셋들이 작동하기 시작합니다.

페이지의 모든 요소는 position: static으로 시작하며, 이는 display와 문서 흐름에서 배운 위에서 아래로 이어지는 일반적인 흐름 속 자리를 뜻합니다. static 요소는 오프셋 속성을 완전히 무시하므로 top이나 left를 설정해도 아무 일도 일어나지 않습니다. 이 부분에서 많은 사람이 헷갈립니다. top: 20px를 추가했는데 변화가 없으니 값이 잘못됐다고 생각하지만, 실제 문제는 position이 빠져 있다는 것입니다.

부드러운 선택지는 **relative 포지셔닝**입니다. 이 속성은 지정한 오프셋만큼 요소를 원래 자리에서 이동시키면서도, 흐름 속 원래 공간은 그대로 예약해둡니다. 이웃 요소들은 그 빈 공간을 채우려고 움직이지 않기 때문에, relative로 위치를 옮긴 요소는 옆에 있는 요소와 겹칠 수 있습니다.

css
.tooltip {
  position: relative;
  top: -4px;                 /* 원래 자리에서 위로 4px 들어올림 */
  left: 8px;                 /* 오른쪽으로 8px 밀림 */
  /* 예약된 공간은 그대로 남고 화면에 그려지는 위치만 바뀜 */
}

top, left 같은 오프셋은 요소에 position이 지정되어야만 적용됩니다. relative 자체는 작은 조정 도구일 뿐입니다. 더 중요한 역할은 absolute로 위치를 지정할 자식 요소를 위한 기준점을 만드는 것인데, 이는 다음 절에서 다룹니다.

position 속성에는 다섯 가지 값이 있는데, 하나의 질문으로 나눠보면 전체 모델을 이해하기가 쉬워집니다. "이 요소는 여전히 일반 흐름 속에서 공간을 차지하는가?"라는 질문입니다. static(초깃값)과 **relative**는 둘 다 공간을 차지하고, absolutefixed는 차지하지 않으며, sticky는 스크롤에 따라 두 동작 사이를 오가는 혼합형입니다.

relativestatic에서 가장 적게 벗어난 형태입니다. 요소는 static일 때와 똑같이 일반 흐름에 따라 배치되고, 그 원래 위치에 공간이 예약된 다음, top / right / bottom / left로 그 위치에서 시각적으로만 오프셋됩니다. 예약된 공간이 절대 움직이지 않기 때문에, relative 요소에 오프셋을 주면 그려지는 위치만 바뀔 뿐 레이아웃이 인식하는 위치는 바뀌지 않으므로, 주변 요소를 밀어내지 않고도 겹칠 수 있습니다.

css
.list-item {
  position: relative;
  top: 6px;                  /* 6px 아래에 그려지지만 흐름 속 자리는 그대로 */
}

정밀하게 봐야 할 두 지점이 있습니다. 첫째, 오프셋은 조상 요소가 아니라 요소 자신의 원래 위치를 기준으로 계산됩니다. top: 10px는 "원래 있어야 할 자리에서 10px 아래"라는 뜻이지, "컨테이너 위쪽에서 10px"라는 뜻이 아닙니다. 둘째, relative 요소에 마주보는 오프셋(topbottom, 또는 leftright)을 함께 지정하면 왼쪽에서 오른쪽, 위에서 아래로 쓰는 방식에서는 시작 쪽이 우선하므로 topbottom을 이기고 leftright를 이깁니다. 실제로 relative를 쓰는 훨씬 더 흔한 이유는 이런 미세 조정이 아니라, absolute 자식 요소를 위한 컨테이닝 블록을 만들기 위해서인데, 이는 다음 절에서 이어집니다.

Junoposition 속성 모든 요소는 static으로 시작하며, 원래 자리에 그대로 있는다는 뜻입니다. position: relative로 바꾸면 top, right, bottom, left로 살짝 밀 수 있고, 원래 공간은 그대로 예약된 채 남습니다. 이 오프셋 속성들은 요소에 position이 지정되어야만 작동하므로, top이 무시되는 것 같다면 먼저 position을 설정했는지 확인하세요.
Junoposition 속성static은 기본값이며 오프셋을 완전히 무시하기 때문에, 일반 요소에 top: 20px를 줘도 아무 일도 일어나지 않습니다. relative는 요소를 원래 자리에서 밀어내면서도 그 공간은 예약된 채로 두므로 이웃 요소가 빈 공간을 채우려고 움직이지 않습니다. 이 밀어내는 기능도 쓸모 있지만, 진짜 이유는 absolute로 위치를 지정할 자식 요소의 기준점을 만드는 것이며, 바로 다음에 다룹니다.
Junoposition 속성 다섯 가지 값을 흐름 속 공간을 유지하는지로 나눠보면, staticrelative는 유지하고, absolutefixed는 유지하지 않으며, sticky는 둘 사이를 오갑니다. relative의 오프셋은 컨테이너가 아니라 요소 자신의 원래 위치를 기준으로 계산되며, 마주보는 오프셋을 함께 주면 시작 쪽이 우선합니다. relative는 밀어내는 도구보다는 absolute 자식의 기준점으로 훨씬 더 많이 쓰입니다.

absolute 포지셔닝

position: absolute는 더 큰 변화입니다. 이 속성은 요소를 일반 흐름에서 완전히 빼내므로 더 이상 공간을 차지하지 않고, 주변 요소들은 마치 그 요소가 없었던 것처럼 자리를 좁혀 채웁니다. 그런 다음 같은 top, right, bottom, left 오프셋으로 위치를 지정합니다.

문제는 "무엇을 기준으로 오프셋을 계산하는가"입니다. absolute 요소는 가장 가까운 **포지션이 지정된 조상**을 기준으로 위치를 잡습니다. 즉, 자기만의 position(static이 아닌 값)을 가진 가장 가까운 부모를 기준으로 삼습니다. 그래서 카드 위 배지 패턴은 항상 짝을 이뤄 등장합니다. 카드를 relative로 만들어 기준점으로 삼고, 배지를 absolute로 만들어 카드의 모서리에 자리 잡게 하는 것이죠.

css
.card {
  position: relative;        /* 기준점이 됨 */
}

.card .badge {
  position: absolute;
  top: 8px;                  /* 카드 위쪽에서 8px */
  right: 8px;                /* 카드 오른쪽에서 8px */
}

카드에 position: relative가 없다면, 배지는 페이지 더 위쪽으로 올라가면서 포지션이 지정된 조상을 찾다가 여러분이 의도하지 않은 곳에 자리 잡게 됩니다.

**absolute 포지셔닝**은 요소를 일반 흐름에서 완전히 제거합니다. 공간을 전혀 차지하지 않고, 이전에 이웃했던 요소들은 마치 그 요소가 사라진 것처럼 서로 붙게 되며, 그런 다음 오프셋 속성으로 위치를 지정합니다. 오프셋은 요소의 컨테이닝 블록, 즉 자기 자신이 포지션이 지정된 가장 가까운 조상의 패딩 영역을 기준으로 측정됩니다.

이 "가장 가까운 포지션이 지정된 조상"이라는 규칙이 계속 쓰게 될 패턴의 핵심입니다. 부모에 position: relative를 설정하면(이것만으로는 눈에 보이는 변화가 없습니다) 그 안의 absolute 자식들을 위한 기준 틀이 됩니다.

css
.dropdown {
  position: relative;        /* 기준 틀이 되며, 눈에 보이는 변화는 없음 */
}

.dropdown .menu {
  position: absolute;
  top: 100%;                 /* 트리거 바로 아래 */
  left: 0;                   /* 왼쪽 가장자리에 맞춤 */
  width: 200px;
}

포지션이 지정된 조상이 하나도 없으면, absolute 요소는 초기 컨테이닝 블록, 대략 뷰포트를 기준으로 돌아가며, 대체로 페이지 왼쪽 위 모서리에 자리 잡게 됩니다. absolute 요소가 엉뚱한 곳에 놓이는 경우는 거의 항상 기준으로 삼으려던 부모에 position: relative가 빠져 있는 것이 원인입니다.

absolute로 위치가 지정된 요소는 일반 흐름에서 빠져나옵니다. 흐름 속에 박스를 생성하지 않고, 부모의 높이에 아무런 영향을 주지 않으며, 형제 요소들은 마치 그 요소가 존재하지 않는 것처럼 배치됩니다. 그리고 자신의 컨테이닝 블록을 기준으로 위치가 잡히는데, 이 컨테이닝 블록 규칙을 정확히 아는 것이 "작동은 하는데" 수준과 "작동하는 이유까지 아는" 수준을 가릅니다.

absolute 요소의 컨테이닝 블록은 positionstatic이 아닌 가장 가까운 조상의 패딩 박스입니다. 자격을 갖춘 조상이 여럿이면 가장 가까운 것이 우선합니다. 자격을 갖춘 조상이 하나도 없으면 컨테이닝 블록은 초기 컨테이닝 블록, 즉 문서에 고정된 뷰포트 크기의 사각형이 되며, 그래서 기준을 잡지 못한 absolute 요소는 페이지 왼쪽 위로 흘러가게 됩니다.

css
.field {
  position: relative;        /* 컨테이닝 블록을 만듦 */
  padding: 12px;
}

.field .clear-button {
  position: absolute;
  top: 50%;
  right: 8px;
  transform: translateY(-50%);   /* .field를 기준으로 수직 중앙 정렬 */
  /* 오프셋은 .field의 콘텐츠 박스가 아니라 패딩 박스를 기준으로 측정됨 */
}

사람들을 놀라게 하고 컨테이닝 블록의 고급 원리에서도 중요한 규칙이 하나 있습니다. 조상 요소의 transform, filter, will-changeposition이 설정되어 있지 않아도 absolute 자식을 위한 컨테이닝 블록을 만듭니다. 그러니 absolute 자식이 여러분이 기준점으로 생각지도 않았던, transform이 걸린 조부모 요소로 갑자기 오프셋의 기준을 옮겨갈 수 있습니다. absolute 요소가 "잘못된" 요소를 기준으로 위치가 잡힌다면, position뿐 아니라 트리 위쪽에 숨어 있는 transform도 확인해보세요.

Junoabsolute 포지셔닝position: absolute는 요소를 흐름에서 빼내므로 공간을 차지하지 않고 이웃 요소들이 그 자리를 채웁니다. 그런 다음 position이 설정된 가장 가까운 부모를 기준으로 위치가 잡힙니다. 그래서 카드 위 배지 트릭은 짝으로 씁니다. 카드에는 relative, 배지에는 absolute를 줘야 배지가 카드 모서리에 자리 잡지, 엉뚱한 곳에 가지 않습니다.
Junoabsolute 포지셔닝 absolute 요소는 흐름에서 완전히 벗어나 컨테이닝 블록, 즉 자기 자신이 포지션이 지정된 가장 가까운 조상을 기준으로 위치가 잡힙니다. 흔히 쓰는 패턴은 부모에 position: relative를 주는 것인데, 눈에 보이는 변화는 없지만 기준 틀이 되고, 그 뒤 자식에 absolute를 줍니다. absolute 요소가 페이지 왼쪽 위 모서리에 놓인다면, 포지션이 지정된 조상이 하나도 없어서 뷰포트를 기준으로 잡혔다는 뜻입니다.
Junoabsolute 포지셔닝 absolute 요소의 컨테이닝 블록은 static이 아닌 가장 가까운 조상의 패딩 박스이며, 그런 조상이 없으면 뷰포트입니다. 함정은 transform, filter, will-changeposition 없이 컨테이닝 블록을 만든다는 점입니다. 그래서 자식이 여러분이 잊고 있던, transform이 걸린 조부모를 기준으로 자리 잡을 수 있습니다. 오프셋이 잘못된 요소를 기준으로 잡힌다면, position이 빠졌는지뿐 아니라 트리에 숨어 있는 transform도 훑어보세요.

fixed와 sticky

position: fixed는 요소를 화면 자체에 고정합니다. absolute처럼 흐름에서 빠져나오지만, 부모를 기준으로 삼는 대신 눈에 보이는 창인 **뷰포트**를 기준으로 삼습니다. 한번 fixed로 지정되면 페이지를 스크롤해도 화면상 같은 위치에 계속 머뭅니다. 내비게이션 바나 "맨 위로" 버튼이 항상 화면에 보이는 이유가 바로 이것입니다.

css
.site-header {
  position: fixed;
  top: 0;                    /* 창 위쪽에 고정 */
  left: 0;
  right: 0;                  /* 전체 너비로 늘어남 */
}

position: sticky는 친근한 중간 지점입니다. sticky 요소는 평소에는 페이지와 함께 스크롤되다가, 지정한 기준점에 도달하면 그 위치에 붙어버립니다. 콘텐츠와 함께 위로 스크롤되다가 화면 위쪽에서 멈춰 서는 섹션 제목이 대표적인 예입니다.

css
.section-title {
  position: sticky;
  top: 0;                    /* 위쪽 가장자리에 도달하면 붙음 */
}

**fixed 포지셔닝**은 absolute와 비슷하게 동작하지만, 컨테이닝 블록이 조상이 아니라 항상 뷰포트라는 점이 다릅니다. fixed 요소는 흐름에서 제거된 다음 화면 속 고정된 위치에 박히므로, 페이지를 스크롤해도 움직이지 않습니다. 그래서 상단 바, 쿠키 배너, 플로팅 액션 버튼처럼 항상 떠 있어야 하는 UI에 적합합니다.

css
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 64px;
  /* 아래 콘텐츠에 padding-top: 64px를 줘야 가려지지 않음 */
}

이 주석이 가장 흔한 함정을 짚고 있습니다. fixed 헤더는 흐름 밖에 있기 때문에 아래 콘텐츠와 겹치므로, 보통 페이지 본문에 그만큼의 padding이나 margin을 추가해 콘텐츠를 밀어내야 합니다.

sticky 포지셔닝은 혼합형입니다. 화면에 보이는 동안은 relative처럼 동작하다가, top, bottom, left, right 중 지정한 기준점에 도달하면 fixed와 비슷한 동작으로 전환됩니다. 이런 기준점 오프셋이 없는 sticky 요소는 절대 붙지 않습니다. 붙을 기준선이 없기 때문입니다.

css
.section-title {
  position: sticky;
  top: 16px;                 /* 위쪽에서 16px 지점에 도달하면 그 자리를 유지 */
}

fixed는 컨테이닝 블록이 뷰포트라는 중요한 차이 하나를 가진 absolute입니다. 그래서 화면에 고정되어 문서와 함께 스크롤되지 않습니다. 이 때문에 항상 떠 있어야 하는 UI에 적합하지만, 두 가지 주의할 점이 있습니다. 흐름 속 콘텐츠와 겹치므로(본문에 padding을 줘서 공간을 확보해야 합니다) absolute에서 본 "transform이 컨테이닝 블록을 만든다"는 규칙이 여기서도 적용되어, 조상의 transformfixed 요소를 그 조상 안에 가둬버려 함께 스크롤되게 만들 수 있습니다. "fixed"인데 이상하게 스크롤되는 요소는 대개 transform이 걸린 조상 아래에 있는 경우입니다.

**sticky 포지셔닝**은 다섯 가지 값 중 가장 조건이 복잡합니다. sticky 요소는 일반 흐름에 배치되어 공간을 유지하다가, 가장 가까운 스크롤 조상이 지정된 기준점까지 스크롤될 때까지 그대로 있습니다. 그 시점부터는 컨테이닝 블록이 그 지점을 지나칠 때까지 기준점에 붙어 있고, 그 지점을 지나면 풀려납니다. 사람들이 자주 놓치는 두 가지 요구 사항이 있습니다.

css
.toc {
  position: sticky;
  top: 24px;                 /* 기준점; 오프셋이 없으면 절대 붙지 않음 */
  /* .toc의 부모가 화면에 남아 있는 동안만 붙음 */
}

첫째, sticky는 top, bottom, left, right 중 기준점 오프셋이 필요합니다. 이게 없으면 붙을 기준선이 없어 그냥 평범한 relative 요소처럼 동작합니다. 둘째, sticky는 부모의 범위 안에서만 붙을 수 있으므로, 부모가 짧으면 부모가 화면 밖으로 스크롤되는 순간 요소도 풀려납니다. 그리고 자주 조용히 실패하는 경우로, overflow: hidden, scroll, auto가 걸린 조상은 sticky 요소의 스크롤 컨테이너가 되어버려서, sticky 항목이 여러분이 예상한 것과 다른 컨테이너에 갇혀 조용히 아무 동작도 하지 않을 수 있습니다.

Junofixed와 stickyposition: fixed는 요소를 화면에 고정하므로 스크롤해도 그 자리에 그대로 있고, 이 덕분에 헤더나 맨 위로 버튼이 계속 화면에 남습니다. position: sticky는 중간 지점으로, 페이지와 함께 스크롤되다가 top: 0 같은 기준점에 도달하면 붙습니다. fixed는 아래에 있는 콘텐츠와도 겹치므로, 가려질 콘텐츠를 위한 공간을 남겨두세요.
Junofixed와 stickyfixed는 뷰포트를 기준으로 잡는 absolute라서, 페이지를 스크롤해도 화면에 그대로 남지만, 주변에 padding을 주지 않으면 흐름 속 콘텐츠와 겹칩니다. sticky는 기준점 오프셋에 도달하기 전까지는 relative처럼 동작하다가, 도달하면 그 자리에 고정됩니다. top이나 bottom이 없는 sticky 요소는 절대 붙지 않습니다. 붙을 기준선이 없기 때문입니다.
Junofixed와 stickyfixed는 뷰포트를 기준으로 고정되지만, 조상의 transform이 그것을 그 조상 안에 가둬버려서 함께 스크롤되게 만들 수 있으므로, 스크롤되는 "fixed" 요소는 대개 transform이 걸린 부모를 갖고 있습니다. sticky는 사람들이 자주 놓치는 두 가지가 필요합니다. 기준점 오프셋과 충분히 긴 부모인데, 부모가 화면 밖으로 스크롤되는 순간 풀려나기 때문입니다. 그리고 overflow가 설정된 조상을 조심하세요. 그 조상이 스크롤 컨테이너가 되어 조용히 sticky를 무력화할 수 있습니다.

z-index로 쌓기

요소들이 겹치면 어느 것을 앞에 둘지 결정해야 합니다. 이를 결정하는 것이 z-index입니다. z-index 값이 클수록 앞쪽에 그려지므로, z-index: 10인 드롭다운이 z-index: 1인 카드를 덮습니다.

모두가 걸려 넘어지는 규칙이 하나 있습니다. z-index는 포지션이 지정된 요소에만 작동합니다. 요소가 아직 static이라면 z-index는 무시됩니다. 그래서 거의 항상 positionz-index를 함께 설정합니다.

css
.modal {
  position: fixed;
  z-index: 100;              /* 일반 페이지 콘텐츠 위에 위치 */
}

.modal-overlay {
  position: fixed;
  z-index: 99;               /* 어두운 배경, 모달보다 한 단계 아래 */
}

여기서 큰 숫자를 쓸 필요는 거의 없습니다. 1, 10, 100 같은 작고 정돈된 규모가 서로 부딱치는 9999들로 가득한 페이지보다 이해하기 훨씬 쉽습니다.

두 요소가 겹치면 z-index가 앞뒤 순서를 정합니다. 큰 숫자가 작은 숫자 위에 그려집니다. 함정은 **z-index가 포지션이 지정된 요소에만 영향을 준다**는 점입니다. static 요소에 z-index를 줘도 아무 일도 일어나지 않으므로, z-indexposition은 거의 항상 함께 다닙니다.

css
.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
}

.tooltip {
  position: absolute;
  z-index: 50;               /* 카드보다 위, 모달보다 아래 */
}

일찍부터 길러둘 습관은 숫자를 계속 키우는 것이 아니라 작고 의도적인 규모를 쓰는 것입니다. 무언가를 이기려고 z-index: 9999를 쓰고 있다면, 진짜 해결책은 대개 z-index 값 체계를 세우는 것이지 더 큰 숫자가 아닙니다. 다음 레벨에서는 왜 큰 숫자가 그래도 지는 경우가 있는지를 설명합니다.

z-index는 z축을 따라 겹치는 포지션 지정 요소의 순서를 정하며, 큰 값이 앞쪽에 오고, static 요소에는 무시됩니다. 5분짜리 버그를 한 시간짜리로 만드는 부분은 스택 컨텍스트입니다. 스택 컨텍스트는 그 안에서 z-index 값들이 서로 비교되는 독립된 그룹으로, 형제 요소들에 대해 하나의 단위로 쌓입니다.

스택 컨텍스트는 요소가 auto가 아닌 z-index와 함께 포지션이 지정될 때 만들어지지만, opacity1 미만일 때, 어떤 transform이든, filter, will-change, isolation: isolate, 그리고 몇 가지 다른 속성에서도 만들어집니다. 중요한 점은 z-index는 오직 같은 스택 컨텍스트 안에서만 비교된다는 것입니다. 어떤 요소가 특정 컨텍스트 안에 들어가면, 그 요소의 z-index는 숫자가 얼마나 크든 그 컨텍스트 밖의 요소보다 위로 올라갈 수 없습니다.

css
.card {
  opacity: 0.98;             /* 이것만으로도 스택 컨텍스트가 만들어짐 */
}

.card .badge {
  position: absolute;
  z-index: 9999;             /* .card의 컨텍스트 안에 갇힘 */
}

.sibling-panel {
  position: relative;
  z-index: 2;                /* 여전히 .badge보다 위에 그려짐 */
}

여기서 9999.badge2.sibling-panel에 지는 이유는, .badge.cardopacity가 만든 컨텍스트에 갇혀 있고, 그 컨텍스트 전체가 .sibling-panel보다 순위가 낮기 때문입니다. 높은 z-index가 이기지 못한다면, 답은 거의 항상 더 큰 숫자가 아닙니다. 조상 어딘가가 조용히 스택 컨텍스트를 열어놓은 것이며(흔히 opacitytransform), 해결책은 그 조상의 값을 올리거나 그 조상을 분리하는 것입니다.

마지막으로 판단력에 관한 이야기를 하나 덧붙이면, 포지셔닝과 z-index는 오버레이, 배지, 고정 UI처럼 흐름에서 벗어나거나 위에 떠 있어야 하는 것들을 위한 도구입니다. 페이지의 주요 구조를 짜기에는 맞지 않는 도구입니다. 콘텐츠와 뷰포트에 반응해야 하는 행, 열, 그리드에는 flexbox박스 모델에서 배운 박스 모델 기반 흐름을 쓰고, 포지셔닝은 그 위에 떠 있는 레이어를 위해 남겨두세요.

Junoz-index로 쌓기 요소들이 겹치면 z-index가 어느 것을 앞에 둘지 결정합니다. 큰 숫자가 이깁니다. 포지션이 지정된 요소에만 작동하므로, 일반 static 요소에 준 z-index는 무시되며, 그래서 positionz-index를 함께 설정합니다. 숫자는 1, 10, 100처럼 작고 정돈되게 유지하고, 9999를 쌓아 올리지 마세요.
Junoz-index로 쌓기z-index는 포지션이 지정된 요소의 앞뒤 순서를 정하며, static 요소에는 아무 효과가 없으므로 position과 함께 다닙니다. 숫자를 계속 올리기보다 작고 의도적인 규모를 쓰세요. 이기려고 9999를 쓰고 있다면 더 큰 값이 아니라 체계가 필요한 겁니다. 그리고 때로는 더 큰 값도 지는데, 이는 스택 컨텍스트를 다루는 심화 학습에서 설명합니다.
Junoz-index로 쌓기z-index는 스택 컨텍스트 안에서만 비교되며, 1 미만의 opacity, transform, filter 같은 것들이 조용히 새 컨텍스트를 만듭니다. 그래서 z-index: 9999인 자식이 바깥의 2짜리 요소에도 질 수 있는 겁니다. 자기 조상의 컨텍스트에 갇혀 있는 것이죠. 높은 숫자가 이기지 않는다면 컨텍스트를 연 조상을 찾아 그 값을 올리고, 포지셔닝은 페이지 레이아웃이 아니라 오버레이를 위해 남겨두세요.