연재의 마지막 회차입니다. 지금까지 순서를 정하고, 기준선을 콘텐츠에서 뽑고, 크기를 유동으로 만들고, 그리드 칸이 부풀지 않게 하고, 가로 넘침을 찾아내고, 누를 수 있는 크기를 확보하고, 내비게이션을 정리했습니다. 마지막은 position: sticky 입니다 — 이 속성은 실패할 때 아무 말도 하지 않기 때문에 유독 시간을 많이 잡아먹습니다.
조건 셋 — 순서대로 확인합니다
첫째, 임계값이 있어야 합니다. position: sticky 만 쓰고 top · bottom 중 어느 것도 지정하지 않으면 붙을 기준선이 없어 아무 일도 일어나지 않습니다. top: 0 한 줄이 빠진 경우가 놀랄 만큼 흔합니다.
둘째, 부모 안에 움직일 여유가 있어야 합니다. 고정 요소는 화면이 아니라 부모 상자 안에서 움직이고 부모의 아래 끝에서 멈춥니다. 부모가 자기 내용만큼만 높으면 이동할 거리가 0 이므로 붙는 것처럼 보이지 않습니다. 그리드나 플렉스에서 특히 자주 나옵니다 — 항목이 기본적으로 늘어나 행 높이를 채우기 때문에, 고정 요소 자신이 이미 전체 높이가 되어 움직일 수 없습니다. 그 항목에 align-self: start 를 주면 높이가 내용만큼으로 줄고 이동할 여유가 생깁니다.
셋째, 조상의 overflow 입니다. 이것이 가장 자주 나오고 가장 늦게 발견됩니다.
조상 하나가 전체를 무력화합니다
고정 요소는 가장 가까운 스크롤 컨테이너를 기준으로 붙습니다. 조상 중 하나라도 overflow 가 visible 이 아니면 그 조상이 스크롤 컨테이너가 되고, 고정 요소는 그 안에서 붙으려 합니다. 그런데 그 상자가 스크롤되지 않으면 붙을 일 자체가 없습니다 — 그래서 화면에서는 그냥 평범한 요소로 보입니다.
여기에 지난 회차의 이야기가 이어집니다. 가로 넘침을 덮으려고 body { overflow-x: hidden; } 을 넣으면 세로 쪽이 자동으로 스크롤 값이 되고, 그 순간 사이트 전체의 고정 헤더와 고정 목차가 한꺼번에 멈춥니다. 두 증상이 서로 다른 페이지에서 나타나므로 인과를 연결하기가 특히 어렵습니다.
hidden 과 clip 은 다릅니다
내용을 잘라 내고 싶을 뿐이라면 overflow: clip 이 있습니다. 잘라 내되 스크롤 컨테이너를 만들지 않으므로 그 안의 고정 요소가 계속 문서 스크롤을 기준으로 동작합니다. 장식 배경을 자르는 구역에는 hidden 대신 clip 을 쓰는 것이 기본값이 될 만합니다.
원인을 빨리 찾으려면 조상을 거슬러 올라가며 계산된 값을 찍어 봅니다. for (let p = el.parentElement; p; p = p.parentElement) { const s = getComputedStyle(p); if (s.overflow !== 'visible' || s.overflowX !== 'visible' || s.overflowY !== 'visible') console.log(p, s.overflow, s.overflowX, s.overflowY); } 한 줄이면 범인이 바로 나옵니다.
고정 헤더가 앵커를 가릴 때
고정 헤더가 동작하기 시작하면 새 문제가 하나 따라옵니다. 목차 링크를 눌러 이동했을 때 해당 제목이 헤더 뒤에 숨습니다. 해결은 제목 쪽에 scroll-margin-top 을 주는 것입니다.
다만 그 값을 헤더 높이 상수 하나로 두면 안 됩니다. 좁은 화면에서 헤더가 두 줄로 접히면 실제 높이가 훨씬 커지고, 그때 데스크톱 값으로는 제목이 여전히 가려진 채 남습니다. 화면이 “조금 위로 간” 정도로만 보여서 고장으로 인식되지 않는 종류의 문제입니다. 값은 브레이크포인트마다 실제 높이를 재서 넣습니다.
연재를 마치며
여덟 회차를 관통한 생각은 하나였습니다. 깨진 곳을 찾아 기준선을 더하는 대신, 애초에 깨지지 않는 구조를 만든다. 순서를 좁은 화면에서 확정하고, 기준선을 콘텐츠에서 뽑고, 크기를 유동으로 두고, 트랙의 최솟값을 명시하고, 넘침을 요소 단위로 찾고, 손가락 기준으로 크기를 잡고, 감출 것과 보일 것을 나누고, overflow 한 줄이 무엇을 무력화하는지 압니다.
운영 중인 사이트에서 이 정비를 한 번에 처리하려면 최적화 지원 사업이 있고, 실제로 어떤 순서로 작업하는지는 작업 과정에 절차 그대로 공개돼 있습니다. 화면 구조와 관련한 다른 글은 테마 · 플러그인 아카이브에서 이어집니다.