스크롤 위치가 원하는 곳으로 가지 않고 꼬인다면? - scroll-margin-top

작성일: 2026년 3월 15일 오후 05:15(마지막 수정: 2026년 3월 27일 오후 07:05)
조회수: 22

[React] 토글 접을 때 스크롤 위치가 꼬인다면? (feat. CSS의 마법)

리액트에서 긴 컨텐츠를 토글(Toggle)로 만들 때, 하단 버튼을 눌러 컨텐츠를 접으면서 다시 위로 스크롤 시키는 기능을 구현하다 보면 예상치 못한 난관에 부딪히곤 합니다. 분명 scrollIntoView를 썼는데 왜 헤더가 잘리거나 위치가 이상할까요?

1. 범인은 '레이아웃의 변화'와 '오프셋'

보통 상단에 고정된(Sticky/Fixed) 메뉴가 있는 경우, scrollIntoView는 요소의 최상단을 브라우저의 최상단(0,0)에 맞추려 합니다. 결과적으로 내 소중한 타이틀이 고정 헤더 뒤로 숨어버리는 현상이 발생하죠.

스크린샷 2026-03-16 오전 2.07.20.png

헤더 저 밑 어딘가에 뭔가 있다..

2. 해결사: scroll-margin-top

CSS 한 줄이면 해결됩니다.

css
/* 이동하고 싶은 목적지 요소에 추가 */
.toggle-header {
  /* 상단 고정 헤더의 높이 + 여유 공간만큼 설정 */
  scroll-margin-top: 80px; 
}
jsx
// tailwindcss의 경우
<div ref={targetRef} className={"scroll-m-16"} >
...
</div>

이 속성은 브라우저에게 이렇게 말하는 것과 같습니다: "야, 이 요소로 스크롤 할 때 위에 80px 정도는 여유 좀 줘!"

이를 통해 레이아웃 자체에 영향을 주는 Margin을 사용할 방법을 고려하거나, 복잡하게 좌표를 계산하여 직접 스크롤(window.scrollTo({ top: ... }))할 필요 없습니다.

3. 전체 흐름도

토글이 닫히면서 스크롤이 이동하는 과정을 시각화하면 다음과 같습니다.

mermaid

4. 최종 코드 스니펫(예시)

CSS

css
.accordion-header {
  scroll-margin-top: 100px; /* 고정 헤더보다 조금 더 여유 있게 */
  transition: all 0.3s;
}

React Component

jsx
const handleCollapse = () => {
  // 1. 상태 변경 (컨텐츠 접기)
  setIsExpanded(false);

  // 2. 스크롤 이동 (CSS가 위치를 보정해줌)
  headerRef.current?.scrollIntoView({
    behavior: "smooth",
    block: "start",
  });
};

마치며

스크롤 문제는 JS 문제 같아 보이지만, 의외로 CSS로 해결할 때 가장 깔끔합니다. scroll-margin-top은 브라우저 호환성도 좋으니(IE 제외) 적극 활용해 보세요!

0개의 댓글
💬

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!