Early Riser
생각정리
Early Riser
전체 방문자
오늘
어제
  • 분류 전체보기 (128)
    • JS (19)
    • React (33)
    • React Native (2)
    • Library, Tool (13)
    • CSS (2)
    • Algorithm (40)
    • Computer Science (3)
    • 회고 (3)
    • AI (13)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 글쓰기

공지사항

인기 글

태그

  • 비동기
  • 백준
  • 부스트캠프 합격
  • 알고리즘
  • 프로그래머스
  • 파이썬
  • useState
  • js
  • 손실함수
  • boosting
  • lightgbm
  • useEffect
  • react
  • LGBM
  • RNN
  • 부스트캠프 9기
  • 논문리뷰
  • BFS
  • 부스트캠프 합격 후기
  • javascript
  • 구현
  • dfs
  • 오늘의불경
  • 밑바닥
  • 완전탐색
  • local minima
  • 딥러닝
  • 자바스크립트
  • 백트래킹
  • global minima

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Early Riser

생각정리

CSS

Staking Context와 Position, z-index 그리고 React Portal

2025. 11. 21. 10:43

서론

 Fe 개발자라면 한번쯤은 CSS에서 position: fixed 요소가 스크롤을 따라오지 않거나 z-index가 제대로 먹히지 않는 현상을 경험했을 것이다. 대부분의 개발자는 “z-index를 더 높이면 되겠지”라고 생각하지만, 실제로는 해결되지 않는다. 이 문제의 원인은 stacking context이며, 특히 transform, opacity, filter 같은 속성이 새로운 stacking context를 만들기 때문이다.

Stacking Context란 

Stacking Context는 HTML element들을 3차원적으로 바라보는 개념이다. 우리가 평소 생각하는 X축(가로)과 Y축(세로)에 더해 Z축(깊이)이 추가된다고 이해하면 된다. 이 Z축이 바로 어떤 element가 다른 요소 위에, 혹은 아래에 그려질지를 결정한다.

새로운 Stacking Context를 만드는 조건

다음 조건 중 하나라도 요소에 적용되면 그 요소는 새로운 stacking context를 생성한다.

  • position이 static이 아니면서 z-index가 auto가 아닌 값
  • transform이 none이 아닌 값
  • opacity가 1 미만
  • filter, perspective, backdrop-filter가 none이 아닌 값
  • contain: layout / paint / style
  • will-change에 위 속성들을 명시

이 조건들 중이 해당 되는 block element라면, 그 block element는 새로운 staking context를 만든다.

 

 따라서 position과 z-index가 둘 다 지정되지 않은 (또는 position: static인) element들은 새로운 stacking context를 생성하지 않는다. 이들은 항상 부모가 만든 가장 가까운 stacking context에 종속된다.

 문서 최상위에는 <html> element가 만든 root stacking context가 하나 존재한다. 새로운 staking context를 만드는 element가 없으면 문서 내 모든 element가 이 root stacking context 안에 속한다.

그런데 그 안에서 가장 많이 사용되는 css 조합인 position: relative/absolute/fixed/sticky이고 z-index가 auto가 아닌 값을 가진 element가 나타나면, 그 element는 새로운 stacking context를 생성한다. 그 element의 모든 자손 element들은 이제 상위 context(이 예시의 경우, root element가 만든 staking context)가 아니라 새로 만들어진 이 context에 속한다.

 반대로 position: static이거나 z-index: auto인 element들은 새로운 context를 만들지 않는다. 따라서 이들은 계속 상위 stacking context 안에 머무른다.

 즉, 새로운 stacking context를 만드는 element가 나타나기 전까지는 모든 block element와 inline element가 동일한 하나의 stacking context 안에서 쌓인다. 이 안에서는 position: static element에 z-index를 줘도 완전히 무시되며, HTML element 순서만이 순서를 결정한다. 나중에 나온 element가 항상 위에 그려진다.

 아래 예시를 보자.

<div class="a">A</div>
<div class="b">B</div>

<div class="new-context" style="position:relative; z-index:5;">
  <div class="child">자식</div>
</div>

A와 B는 root stacking context에 속하고, 자식은 .new-context가 만든 별도의 stacking context에 속한다. 자식에 z-index: -999를 줘도 A나 B보다 아래로 내려가지 않는다. 새로운 context 전체가 root보다 위에 쌓이기 때문이다.

 position: fixed도 마찬가지이다. 원래는 position:fixed는 viewport를 기준으로 고정되어야 한다. 그러나 조상 element에 transform, opacity < 1, filter 등이 있으면 fixed조차 그 조상 element의 stacking context에 속한다. 따라서 스크롤해도 움직이지 않고, z-index도 그 context 안에서 우선순위를 가지게 된다.

React Portal

 html element가 어떤 stacking context의 영향도 받지 않으려면, 그 element를 stacking context를 전혀 생성하지 않는 element의 직계 자식으로 만들어야 한다. HTML 문서에서 그런 위치는 오직 <body>의 직계 자식뿐이다.

const modalDialog = ... // get the dialog where the button is clicked
document.getElementByClassName('body')[0].appendChild(modalDialog);

 그러나 react에서는 object mutation을 권장하지 않는다. effect로 사용할 순 잇지만, reconcilation을 거치고 나서 다시 append하는 것은 성능 상 안좋을 것이다. 이럴때 쓰는 것이 React의 ReactDOM.createPortal 컴포넌트이다. 

'CSS' 카테고리의 다른 글

WCAG를 준수하는 반응형 text 만들기  (0) 2026.02.02
    'CSS' 카테고리의 다른 글
    • WCAG를 준수하는 반응형 text 만들기
    Early Riser
    Early Riser
    2년차 프론트엔드 개발자입니다. https://github.com/EarlyRiser42

    티스토리툴바