사이드바 메뉴나 목차에 position: sticky 속성을 적용했는데 고정되지 않고 그냥 지나쳐 버리는 현상을 겪어보셨다면, 혼자가 아닙니다.

이 글에서는 제가 직접 겪었던 실제 사례를 바탕으로 다음 내용을 다룹니다.
- 스티키(sticky) 포지셔닝이 실패하는 진짜 이유
- 개발자 도구(DevTools)에서 올바르게 진단하는 방법
html및body의 overflow가 원인이었던 이유와 해결 방법
재현 가능한 단계별 분석과 함께 알아보겠습니다.
position: sticky에 대한 흔한 오해
CSS 코드가 다음과 같이 완벽해 보일 수 있습니다.
.category-toc {
position: sticky;
top: 100px;
}그럼에도 불구하고 다음과 같은 문제가 계속 발생합니다.
position: sticky가 설정되어 있는데도 아무 일도 일어나지 않음top가 정의되어 있음- 어떤 부모 요소에도
overflow: hidden가 없음 (그렇다고 생각함)
그럼에도 스티키가 작동하지 않는다면, 선언 자체는 문제없지만 구조적인 무언가가 뒤에서 이를 무효화하고 있을 확률이 높습니다.
가장 먼저 확인해야 할 것 (개발자 도구로 진단하기)
크롬(또는 엣지) 개발자 도구를 열고 콘솔(Console) 탭으로 이동한 뒤 아래 코드를 실행해 보세요.
const el = document.querySelector('.category-toc');
getComputedStyle(el).position
getComputedStyle(el).top
getComputedStyle(el).overflow[!NOTE] 콘솔에 코드를 처음 붙여넣는 경우, 크롬에서 보안상 이유로 수동으로 “allow pasting”을 입력해야 할 수 있습니다.
정상적인 결과의 모습
position: "sticky"
top: "100px"
overflow: "visible"이 값들이 올바르게 나오다면 sticky 선언 자체에는 문제가 없습니다.
이 점을 확인했는데도 여전히 고정되지 않는다면, 원인은 다른 곳에 있습니다.
가장 흔한 근본 원인: html / body의 overflow
제 경우의 범인은 html과 body의 overflow 설정이었습니다.
콘솔을 확인해보니 다음과 같은 결과가 나왔습니다.
{
scrollingElement: 'html',
htmlOverflow: 'hidden auto',
bodyOverflow: 'auto'
}이는 실질적으로 다음을 의미했습니다.
html:overflow-x: hidden; overflow-y: autobody:overflow: auto
즉, 두 개의 독립된 스크롤 컨테이너가 동시에 활성화되어 있던 것입니다.
html/body의 overflow가 sticky를 깨뜨리는 이유
position: sticky는 다음 요소를 기준으로 위치를 계산합니다.
- 가장 가까운 스크롤 조상 요소, 또는
- 조상 요소가 없는 경우 뷰포트
하지만 다음과 같은 상황에서는:
html도 스크롤 가능하고body도 스크롤 가능하며- 그 위에 래퍼(wrapper) 요소까지 얹혀 있을 때
…브라우저는 sticky 요소를 어떤 컨테이너에 고정해야 할지 안정적으로 판단하지 못합니다. 그 결과, 요소가 sticky 포지셔닝을 완전히 무시하는 것처럼 보이게 됩니다.
해결 방법: html이 스크롤을 담당하게 하고 body를 기본 흐름으로 돌려놓기
가장 확실한 해결책은 다음과 같습니다.
html {
overflow-x: hidden;
overflow-y: auto;
}
body {
overflow: visible;
}핵심 포인트
- 수직 스크롤은
html에만 집중시키기 body에는overflow: auto를 설정하지 않기- 가로 스크롤 방지를 위한
overflow-x: hidden설정은 유지해도 무방함
이 변경 사항을 적용하자마자, 작동을 거부하던 sticky 요소가 즉시 정상적으로 작동하기 시작했습니다.
콘솔에서 라이브로 먼저 테스트해보기
실제 CSS 파일을 수정하기 전에, 콘솔에서 임시로 이 동작을 테스트해볼 수 있습니다.
document.documentElement.style.overflowY = 'auto';
document.documentElement.style.overflowX = 'hidden';
document.body.style.overflow = 'visible';이 코드를 실행한 후 sticky가 작동하기 시작한다면, overflow가 원인임을 확실히 진단한 것입니다.
다음과 같은 일반적인 회귀(Regression) 주의하기
나중에 코드베이스에 다음과 같은 요소가 추가되면 스티키 포지셔닝이 다시 깨질 수 있습니다.
html { overflow: hidden }상태를 영구적으로 남겨두는 모달 구현- 관련 없는 이유로
body { overflow: auto }를 설정하는 레이아웃 코드 - 자체 overflow 제어 기능이 결합된
height: 100vh래퍼
모달이 열려 있는 동안 스크롤을 막아야 한다면, overflow: auto를 기본 상태로 유지하고 모달이 활성화된 동안에만 hidden로 전환하는 것이 더 안전합니다.
html {
overflow-y: auto;
overflow-x: hidden;
}
.modal-open html {
overflow: hidden;
}요약: sticky가 작동하지 않을 때 확인할 사항
position와top가 올바르게 보인다고 해서 안심하지 않기- 바로 위의 부모뿐만 아니라
html와body의overflow확인하기 - 페이지에 활성화된 스크롤 컨테이너가 오직 하나뿐인지 확인하기
대부분의 경우 sticky 포지셔닝 문제는 sticky 자체를 잘못 작성해서라기보다는 페이지가 실제로 어디서 스크롤되고 있는지에 기인합니다.
이 글로 다른 분들도 불필요한 디버깅 시간을 아끼실 수 있기를 바랍니다.
