LabHub
배우기 러닝패스 코스

CSS — The Later Rule Wins

Finding the Reason in the Ancestors

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

담음 블록·스크롤 상자·쌓임 맥락을 조상을 따라 올라가며 직접 계산합니다. 브라우저는 없지만 이 셋은 마크업과 CSS 만으로 답이 정해집니다.

왜 중요한가

fixed 가 안 붙고 sticky 가 안 따라다니는 버그는 증상이 원인을 전혀 가리키지 않습니다. 그 요소의 CSS 는 완벽하게 맞고, 개발자 도구로 그 요소만 보면 아무 문제가 없습니다. 볼 곳은 조상입니다.

조상에 transform 이 하나 있으면 fixed 의 기준이 뷰포트에서 그 조상으로 바뀝니다. 조상에 overflow: hidden 이 하나 있으면 그 상자가 스크롤 상자가 되어 sticky 가 붙을 일이 없어집니다. 카드 호버 효과와 모달은 아무 관계가 없어 보이므로, 규칙을 모르면 원인을 찾기까지 몇 시간이 갑니다.

이 실습의 문서

채점기와 계산기가 아래 구조를 가정합니다. HTML 은 쓰지 않습니다.

div.page
├ header.topbar
└ div.shell
  ├ aside.side
  │ └ nav.toc
  └ main.content
    └ div.card
      ├ span.badge
      └ div.overlay

만들 것

/root/work/pos/layout.css 하나입니다.

계산기

cd /root/work/pos
python3 /opt/lab/checks/css-pos-lab/boxes.py layout.css
python3 /opt/lab/checks/css-pos-lab/boxes.py layout.css 500

요소마다 position · 담음 블록 · sticky 판정 · z-index 범위를 찍습니다. 두 번째 인자로 화면 폭을 주면 그 폭에서 다시 계산합니다.

단계

  1. .badge.card 기준으로 (절대 위치의 담음 블록)
  2. .overlay 를 뷰포트 기준으로 (fixed 의 기본 담음 블록)
  3. transform 을 어디에 두느냐 — fixed 가 갇히는 함정
  4. .topbar 를 sticky 로 (임계값)
  5. .toc 가 실제로 붙게 (스크롤 상자 고르기)
  6. z-index 가 루트에서 겨루게 (쌓임 맥락)
  7. 계산기 결과를 07-boxes.txt
  8. 좁은 화면에서는 목차를 흐름으로 (순서 함정 다시)
  9. 정리 → 09-notes.md

참고

절대 위치의 기준을 만든다

/root/work/pos/layout.css 를 만들고 .badgeposition: absolute 로, 방향을 두 개 이상(예: topright) 주세요. 그 담음 블록이 .card 가 되어야 합니다.

mkdir -p /root/work/pos. absolute 의 담음 블록은 가장 가까운 위치 지정된 조상입니다. relative 는 자기 자리를 그대로 두면서 기준만 만들어 주기 때문에 이 용도로 가장 많이 쓰입니다.

덮개를 뷰포트에 고정한다

.overlayposition: fixed 로 두고 네 방향을 모두 정하세요(inset: 0 한 줄로도 됩니다). z-index 도 주세요. 담음 블록이 뷰포트여야 합니다.

fixed 의 기본 담음 블록은 뷰포트입니다 — 그래서 스크롤해도 따라오지 않고 화면에 붙어 있습니다. 네 방향이 모두 정해져야 화면을 가득 덮습니다.

transform 을 어디에 두는가

.badgetransform 을 주어 모서리 밖으로 살짝 걸치게 하세요. .card 에는 transform·filter·perspective·will-change·contain 중 어느 것도 있으면 안 되고, .overlay 의 담음 블록은 여전히 뷰포트여야 합니다.

먼저 .cardtransform: translateZ(0) 을 넣고 계산기를 돌려 보세요 — .overlay 의 담음 블록이 .card 로 바뀝니다. 그게 이 실습이 보여 주려는 함정입니다. 확인했으면 그 속성을 실제로 움직여야 하는 요소로 옮기세요.

머리띠를 붙인다

.topbarposition: sticky 로 두고 top 을 주세요. 계산기가 '붙는다' 로 판정해야 합니다.

임계값(top·right·bottom·left 중 하나 이상)이 없으면 붙을 선이 없어서 그냥 흘러갑니다. 오류도 경고도 나지 않는다는 점이 이 버그를 오래 살아남게 합니다.

스크롤 상자를 고른다

.tocposition: sticky; top: 64px 로 두고, .pageoverflow-y: auto 를 주어 .page 가 스크롤 상자가 되게 하세요. .shell.side 에는 visible 이 아닌 overflow 가 있으면 안 됩니다.

sticky 는 가장 가까운 스크롤 상자 안에서만 붙습니다. 중간 컨테이너에 overflow: hidden 이 하나 있으면 그것이 스크롤 상자가 되고, 사용자는 그 상자를 스크롤하지 않으므로 붙을 일이 생기지 않습니다. overflow-x: hidden 도 같은 결과를 냅니다.

z-index 가 통하는 범위

.topbarz-index 를 주고, .overlayz-index 가 그보다 크게 하세요. .page·.shell·.content·.card 중 어느 것도 쌓임 맥락을 만들면 안 됩니다.

조상이 쌓임 맥락을 만들면 그 안의 z-index 는 아무리 커도 밖으로 못 나갑니다. opacity: 0.99transform 같은 무심한 한 줄이 그것을 만듭니다. 계산기가 'z-index 가 어느 상자 안에서 통하는지' 를 함께 찍습니다.

계산기로 확인한다

boxes.py 를 돌려 결과를 /root/work/pos/07-boxes.txt 로 남기세요. 출력에 '안 붙는다' 가 없어야 하고, 요소 줄이 잘리지 않고 전부 들어 있어야 합니다.

python3 /opt/lab/checks/css-pos-lab/boxes.py layout.css | tee 07-boxes.txt. 담음 블록 옆의 괄호가 왜 그렇게 정해졌는지를 알려 줍니다 — 조상 이름과 그 속성입니다.

좁은 화면에서는 흐름으로

@media (max-width: 700px) 에서 .tocposition: static 으로 되돌리세요. 넓은 화면(1280px)에서는 여전히 붙어야 합니다. 미디어 쿼리는 기본 규칙 아래에 두어야 합니다.

특정성이 같으면 나중에 쓴 것이 이깁니다. 미디어 쿼리 안이라고 더 센 것이 아닙니다 — 기본 규칙을 미디어 쿼리 아래에 두면 미디어 쿼리는 아무 일도 하지 못합니다. boxes.py layout.css 500 으로 좁은 화면을 확인하세요.

진단 순서를 적어 둔다

/root/work/pos/09-notes.md 에 세 줄 이상(120자 이상) 적으세요. 본문에 담음 블록, transform, overflow 가 들어가야 합니다. 시트도 여전히 앞 단계 기준을 통과해야 합니다.

핵심은 하나입니다 — 원인은 언제나 조상에 있다. 다음에 같은 증상을 만났을 때 조상을 따라 올라가며 무엇을 찾을지 자기 말로 적어 두세요.