기본적으로 z-index는 레이어 순서를 말한다. 포토샵을 생각하면 되는데 바탕이 되는 레이어가 있으면 그 위에 구성 요소들이 쌓이는 식이다.
z-index의 수가 클수록 위로 올라온다. 하지만 단순히 z-index의 값이 큰 것으로만 제어되지 않는 경우가 꽤 있다는 것!
<style>
header {
position: relative;
z-index: 2;
}
.tooltip {
position: absolute;
z-index: 999999;
}
main {
position: relative;
z-index: 1;
}
</style>
<header>
My Cool Site
</header>
<main>
<div class="tooltip">
A tooltip
</div>
<p>Some main content</p>
</main>
위와 같은 코드가 있을 때 가장 위로 올라오는 것은 무엇일까?
단순히 생각하면 999999에 독립적인 포지션을 가지는 툴팁이 가장 위로 올라온다고 생각할 수 있겠지만 헤더에 의해 덮혀진다.
The root context
포토샵의 레이아웃을 묶어서 한 그룹을 짓듯 우리는 요소들을 <div></div>
같은 태그로 묶어 나간다. 하나의 쌓임 맥락은 부모 쌓임 맥락 안에서 통째로 하나의 단위로 간주됩니다. -mdn
요소에 z-index 지정하면 해당 값은 동일한 컨텍스트의 요소와 비교된다. z-index 값은 전역이 아니다.
이런 컨텍스트를 만드는 일반적인 방법은 다음과 같다.
.some-element {
position: relative;
z-index: 1;
}
그럼 위의 예제를 툴팁이 올라오게 하는 방법은 어떻게 될까?
사실 main
은 스택 컨텍스트를 생성할 필요가 없다.
<style>
header {
position: relative;
z-index: 2;
}
.tooltip {
position: absolute;
z-index: 999999;
}
main {
position: relative;
/* No more z-index here! */
}
</style>
<header>
My Cool Site
</header>
<main>
<div class="tooltip">
A tooltip
</div>
<p>Some main content</p>
</main>
Z-index가 없으면 main은 스태킹 컨텍스트를 생성하지 않기 때문에 계층 구조가 달라진다.
The root context
헤더와 툴팁이 이제 동일한 컨텍스트에 있기 때문에 z-인덱스 값을 비교해서 값이 더 큰 툴팁이 위로 올라오게 된다.
여기서 부모/자식 관계에 대해 이야기하는 것이 아닙니다. 툴팁이 헤더보다 더 깊게 중첩되어도 상관 없습니다. 브라우저는 스택 컨텍스트에만 관심이 있습니다. - josh
그런데 만약 main에 z-index값을 사용해야 하거나 스택 컨텍스트를 생성해야하는 상황이라면?
CSS의 규칙에 따르면 쌓이는 컨텍스트를 "해제"할 수 있는 방법은 없다. 한 스택 컨텍스트 내의 요소는 다른 스택 컨텍스트의 요소와 비교할 수 없다.
툴팁값을 <body>
에 부여하고 CSS를 사용해서 적절하게 배치하여 해당 요소의 자식인 것처럼 보이게 할 수 있다 - 고 하는데 이것은 고급 기술이며 키보드를 사용하여 탐색하는 사용자의 경험을 실수로 중단하지 않도록 세심한 계획이 필요합니다 라고 덧붙여있다.😅
z-index, 포지션값 외에
stacking contexts가 생성되는 경우
일반적으로 z-index는 포지셔닝이 설정된 값에서만 작동한다.
그러나 flex에서는 포지션이 기본값(static)인 경우에도 작동한다.
z-색인을 사용하는 것은 일반적으로 상위 스택 컨텍스트에서
다른 요소의 위/아래로 해당 요소를 올리거나 내릴 때이다.
스태킹 컨텍스트가 생성되면 모든 하위 항목을 "평면화"하고 미묘하게 진단하기 어려운 버그를 유발할 수 있다. 하지만 모든 걸 전역적으로 비교하는 것이 과연 좋은 방법이 될까?
.wrapper {
isolation: isolate;
}
isolation
은 가능한 가장 순수한 방법으로 스택 컨텍스트를 생성한다.
브라우저 지원도 우수해서 IE를 고려해야 하는 경우
transform: translate(0px);
대신 사용하는 것도 좋을 것이라고 하는데 트랜스폼 속성 쓰면 써봐야겠다.
맨날 트랜스폼 뭐였더라 하면서 트랜지션 트랜스레이트 트랜스폼 헷갈리는 사람... ✋🏻 저요...
https://www.joshwcomeau.com/css/stacking-contexts/
넓고도 깊은 css의 세계 😶🌫️