1. 문제 발생❓
Next.js 프로젝트에서 랜딩 페이지 템플릿을 개발하던 중, 페이지 최상단에 overflow: hidden 속성을 추가하고 싶었으니 이를 적용하자 Lnb 컴포넌트(sticky 네비게이션 바)가 제대로 동작하지 않는 문제가 발생했습니다.
// 문제가 있는 코드
export default function Template({ userInfo }: Props) {
// ... 코드 생략 ...
return (
<div style={{ backgroundColor: vars.neutral[100], overflow: 'hidden' }}>
<GNB />
<Hero {...heroProps} />
<Lnb menus={LNB_ITEMS} course={course} />
{/* 나머지 콘텐츠 */}
</div>
);
}
2. 원인 추론 🔎
해당 문제의 원인은 CSS positon: sticky와 overflow: hidden 사이의 상호작용에 있었습니다.
- Lnb 컴포넌트는 내부적으로 position: sticky를 사용하여 스크롤 시 화면 상단에 고정되도록 설계되어 있습니다.
- 상위 컨테이너에 overflow: hidden을 적용하면 새로운 스태킹 컨텍스트(stacking context)가 생성됩니다.
- 이로 인해 position: sticky 요소는 뷰포트가 아닌 가장 가까운 스크롤 컨테이너(이 경우 overflow: hidden이 적용된 부모)에 대해 sticky 동작을 수행하게 됩니다.
- 결과적으로 sticky 네비게이션 바가 예상대로 스크롤에 따라 고정되지 않고 비정상적으로 동작했습니다.
여기서 position: sticky란?
- position: sticky는 CSS 포지셔닝 속성으로, 일반 요소와 고정된 요소의 특성을 모두 가진 하이브리드 같은 속성입니다. 쉽게 설명하자면, 사용자가 스크롤하는 동안 특정 지점에 도달하면 화면에 '붙어서' 따라오는 요소를 만들 수 있습니다.
작동 방식
- 처음에는 보통 요소처럼 페이지 흐름에 따라 있습니다.
- 스크롤하다가 지정한 위치(ex: top: 0)에 도달하면
- 그 위치에 "붙어서" 화면을 따라다닙니다.
- 그러다가 부모 요소의 끝에 도달하면 다시 일반적인 흐름을 따릅니다.
간단한 예시
.nav-bar {
position: sticky;
top: 0; /* 화면 상단에 도달하면 거기에 붙습니다 */
}
주의할 점
- 부모 요소에 overflow: hidden이 있으면 sticky가 제대로 작동하지 않을 수 있습니다.
- top, right, bottom, left 중하나 이상을 반드시 지정해야 합니다.
- 요소는 부모 컨테이너 범위 내에서만 sticky 효과가 있습니다.
이렇게 sticky는 스크롤 중에도 계속 보여야 하는 네비게이션 바, 섹션 제목, 필터 등을 만들 때 매우 유용합니다!
3. 해결 과정 📋
이 문제를 해결하기 위해 페이지 구조를 변경하여 overflow: hidden과 position: sitcky가 서로 충돌하지 않도록 했습니다.
- 최상위 div에 overflow: hidden을 적용하는 대신, sticky 요소인 Lnb 아래에 새로운 Wrapper div를 추가하고 그 안에 모든 콘텐츠를 배치했습니다.
- Lnb는 부모에 overflow: hidden이 없으므로 sticky 포지셔닝 뷰포트를 기준으로 정상 작동합니다.
- 그 외 모든 콘텐츠는 overflow: hidde이 적용된 컨테이너 안에 위치하므로 원하는 스타일링이 적용됩니다.
export default function Template({ userInfo }: Props) {
// ... 코드 생략 ...
return (
<div style={{ backgroundColor: vars.neutral[100] }}>
<Portal selector='#portal'>
{/* 포털 컨텐츠 */}
</Portal>
<GNB />
<Hero {...heroProps} />
<Lnb menus={LNB_ITEMS} course={course} />
{/* LNB 아래의 콘텐츠에 대해 overflow: hidden이 있는 래퍼 div 추가 */}
<div style={{ width: '100%', overflow: 'hidden' }}>
{/* 나머지 모든 콘텐츠 */}
<div attribute={TARGET_DATA.introduction}>
<Promotion courseType={course} />
{/* 다른 컴포넌트들... */}
</div>
{/* 나머지 섹션들... */}
<Footer />
<ChannelTalkBtn />
</div>
</div>
);
}
4. 결론 ❤🔥
CSS 스택킹 컨텍스트 이해하기:
- overflow: hidden, position: fixed/sticky, z-index 등의 속성은 새로운 스택킹 컨텍스트를 생성하며, 이는 자식 요소의 동작에 영향을 미칠 수 있습니다!
'인턴' 카테고리의 다른 글
[ Troubleshooting🛠️ ] 모달 표시 문제 해결 (0) | 2025.04.29 |
---|---|
[ Troubleshooting🛠️ ] 모바일 Swiper에서 absolute 요소가 깜박이는 현상 해결 (0) | 2025.04.28 |
Zustand 완전 정복 가이드 (0) | 2025.04.15 |
[성능 최적화⚙️] Set 활용해보기 (1) | 2025.04.14 |
[ Troubleshooting🛠️ ] Tailwind 다크모드 깜박임 현상 해결하기 (0) | 2025.04.14 |