scroll-margin-bottom

요소가 스크롤되어 화면에 들어올 때, 요소의 아래쪽에 확보할 여백을 지정합니다. 고정 푸터나 모바일 액션 바가 스크롤 대상을 가리는 문제를 해결하는 데 주로 쓰이며, 요소의 실제 레이아웃에는 아무 영향도 주지 않습니다.

클래스 목록

패턴: smb{값}{단위}

클래스CSS설명
smb0scroll-margin-bottom: 0스크롤 여백 없음
smb8pxscroll-margin-bottom: 8px8px 여백
smb16pxscroll-margin-bottom: 16px16px 여백
smb2remscroll-margin-bottom: 2rem20px 여백
smb4remscroll-margin-bottom: 4rem40px 여백

라이브 데모

버튼을 누르면 컨테이너를 맨 아래로 보낸 뒤 파란 블록을 아래 정렬로 스크롤해 옵니다. 클래스에 따라 블록이 아래 가장자리에서 얼마나 떨어져 멈추는지 비교해 보세요.

1
2
3
4
대상 블록
6
7
8
9
10

smb0이면 블록이 컨테이너 안쪽 아래 모서리에 딱 붙고, smb4rem이면 40px 위에서 멈춥니다. 블록의 크기나 위치 자체는 전혀 변하지 않습니다.

클래스별 상세

smb0scroll-margin-bottom: 0

스크롤 여백을 0으로 되돌립니다. 공통 레이아웃에서 푸터 보정값이 걸려 있는데 특정 블록만 화면 아래 끝까지 붙여야 할 때 사용합니다.

<!-- Reset an inherited offset for one row -->
<div class="sstym oya h40rem">
  <div class="ssae smb2rem h20rem">Row 1</div>
  <div class="ssae smb0 h20rem">Flush against the bottom edge</div>
</div>

smb8pxscroll-margin-bottom: 8px

8px. 테두리나 포커스 링이 아래 모서리에서 잘리지 않을 정도의 최소 여백입니다. 촘촘한 목록 항목에 적합합니다.

<!-- Message list: keep the focus ring off the bottom edge -->
<div class="oya h40rem df fdc gap8px">
  <article class="smb8px p16px br8px">Message 1</article>
  <article class="smb8px p16px br8px">Message 2</article>
</div>

smb16pxscroll-margin-bottom: 16px

16px. 항목 간격을 16px로 잡은 세로 피드에서 아래 정렬 시 여백을 목록 리듬과 맞춥니다.

<!-- Vertical snap feed with a 16px rhythm -->
<div class="sstym oya h40rem df fdc gap16px">
  <section class="ssae smb16px h30rem">Post 1</section>
  <section class="ssae smb16px h30rem">Post 2</section>
</div>

smb2remscroll-margin-bottom: 2rem

20px. 입력 필드 아래에 나타나는 검증 메시지나 도움말 텍스트가 함께 보이도록 자리를 확보합니다.

<!-- Reserve room for the helper text under a validated field -->
<form class="oya h40rem">
  <div class="smb2rem">
    <label for="email">Email</label>
    <input id="email" class="w100p p12px">
    <p class="fs12px cEF4444">Enter a valid address</p>
  </div>
</form>

smb4remscroll-margin-bottom: 4rem

40px. 높이 40px짜리 고정 푸터, 모바일 하단 액션 바, 쿠키 배너가 스크롤 대상을 가리지 않게 하는 대표적인 값입니다.

<!-- Clear a 40px fixed footer / mobile action bar -->
<article id="terms" class="smb4rem p2rem">
  <h2>Terms</h2>
  <p>Long text...</p>
</article>

<footer class="pf b0 l0 w100p h4rem df jcc aic bg18181B">
  <button class="py12px px2rem br8px bn bg6366F1 cFFFFFF">Agree</button>
</footer>

사용 예시

<!-- Correct scroll target when a fixed footer exists -->
<section id="bottom-section" class="smb4rem">
  <p>The bottom offset keeps it above the 40px fixed footer</p>
</section>

<!-- Bottom margin in vertical scroll snap -->
<div class="ssae smb2rem bg18181B p2rem br8px">
  Reserve extra space below the snap point
</div>

실전 예시: 채팅 입력창이 있는 대화창

메시지를 보낸 뒤 새 말풍선으로 스크롤할 때, 하단에 고정된 입력창 높이만큼 여백을 확보하지 않으면 방금 보낸 메시지가 입력창 뒤에 숨습니다.

<!-- Chat window: after sending, scroll the new message into view so it
     lands above the composer instead of behind it -->
<div class="df fdc h100vh">

  <div id="log" class="obc oya swt fg1 p16px df fdc gap12px">
    <article class="p12px br8px bg18181B">Hi there</article>
    <article id="last" class="smb4rem p12px br8px bg6366F1 cFFFFFF">
      Just sent this one
    </article>
  </div>

  <!-- 40px tall composer pinned to the bottom -->
  <form class="h4rem df aic gap8px px16px bt1pxsolid27272A">
    <input class="fg1 p12px br8px bg0F0F17 bn cFAFAFA">
    <button class="py8px px16px br8px bn bg6366F1 cFFFFFF cp">Send</button>
  </form>
</div>

<script>
document.getElementById('last')
  .scrollIntoView({ behavior: 'smooth', block: 'end' });
</script>

주의사항

스크롤로 들어올 때만 의미가 있습니다

scroll-margin은 앵커 이동, scrollIntoView, 스크롤 스냅처럼 브라우저가 요소를 화면에 맞춰 줄 때만 계산됩니다. 사용자가 직접 스크롤할 때나 일반 레이아웃에는 아무 영향이 없습니다.

아래 정렬일 때만 보입니다

아래쪽 여백은 요소를 아래 기준으로 맞출 때만 반영됩니다. 위 정렬로 스크롤한다면 scroll-margin-top이 필요한 상황입니다. 고정 헤더와 고정 푸터가 모두 있다면 위아래 값을 같이 지정하세요.

값은 실제 푸터 높이와 맞추세요

여백이 푸터보다 작으면 여전히 가려지고, 지나치게 크면 대상이 화면 한가운데 떠 버립니다. 푸터 높이가 자주 바뀐다면 컨테이너 쪽 scroll-padding-bottom으로 한 곳에서 관리하는 편이 낫습니다.