テック技報最新号へ →
CSS

overflow-anchor で、チャット欄を JS なしで常に最下部に張り付かせる

ログ内の要素のスクロールアンカーを全部切り、末尾に置いた高さ 1px の要素だけをアンカーにすると、新しいメッセージが増えても表示が最下部に追従する。

@sanyampunia · 2026-10-28

どんな時に使う?

  • チャット、ログビューア、AI の応答ストリーミングなど、下に行が増えていく欄で「いま一番下を見ている人には新着を見せ続けたい」とき。
  • 追加のたびに scrollTop = scrollHeight を JS で書く処理を減らしたいとき。

コード

html
<div class="log">
  <p>メッセージ1</p>
  <p>メッセージ2</p>
  <!-- 新しいメッセージは .pin の直前に追加する -->
  <div class="pin"></div>
</div>
css
.log {
  overflow-y: auto;
  height: 400px;
}

/* ログの中身はアンカー候補から外す */
.log * {
  overflow-anchor: none;
}

/* 末尾の 1px だけをアンカーにする */
.log .pin {
  overflow-anchor: auto;
  height: 1px;
}

ブラウザのスクロールアンカリングは、内容が増減しても「画面内にある基準の要素」の位置を保とうとする仕組み。基準になれるのが末尾の .pin だけなので、一番下までスクロールしている間は .pin が見え続けるよう位置が保たれ、結果として最下部に張り付く。利用者が上にスクロールして過去ログを読んでいる間は .pin が画面外なので、勝手に下へ戻されない。

注意点

  • 最初の1回は下までスクロールしておく必要がある(初期表示で最下部にしたいなら、読み込み時に一度だけ JS でスクロールするか、flex-direction: column-reverse など別の手を併用する)。
  • メッセージは必ず .pin より前に挿入する。後ろに足すとアンカーが効かない。
  • Safari はスクロールアンカリング(overflow-anchor)に未対応の時期が長かったので、導入前に Can I use で対応状況を確認し、未対応環境では JS のスクロールで補う。

出典

X の元の投稿を開く