Principles and review checklist for building a great streaming chat experience — scroll behavior, auto-scroll, "jump to latest", follow-the- stream, position preservation, and accessibility for LLM/AI chat UIs. Use when building, reviewing, or debugging the scroll and streaming behavior of a chat transcript: auto-scroll pulling the reader around, content jumping while reading, "stick to bottom" logic, new-turn placement, restoring scroll on reopen, or layout shifts from images/markdown/code. Trigger on "scroll engineering", "auto-scroll", "stick to bottom", "jump to latest", "chat scroll", "streaming chat UX", "follow the stream", "scroll jank".
インストール
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
Principles and review checklist for building a great streaming chat experience — scroll behavior, auto-scroll, "jump to latest", follow-the- stream, position preservation, and accessibility for LLM/AI chat UIs. Use when building, reviewing, or debugging the scroll and streaming behavior of a chat transcript: auto-scroll pulling the reader around, content jumping while reading, "stick to bottom" logic, new-turn placement, restoring scroll on reopen, or layout shifts from images/markdown/code. Trigger on "scroll engineering", "auto-scroll", "stick to bottom", "jump to latest", "chat scroll", "streaming chat UX", "follow the stream", "scroll jank".
What Makes a Great Streaming Chat Experience
It's all about the scroll. Scroll Engineering.
This skill codifies the principles for streaming chat UIs. Use it as the
contract when you build chat scroll/streaming behavior, and as the rubric when
you review or debug it.
The one rule everything derives from
Never move the reader against their intent.
Every principle below is a consequence of this. When a decision is ambiguous,
return to this sentence. The reader's attention is the thing you are protecting;
the stream serves the reader, never the other way around.
How to use this skill
Building: treat the 15 principles as acceptance criteria. Each one is a
behavior that must be observably true, not an aspiration.
Reviewing / debugging: walk the review checklist.
Any "no" is a defect against the one rule, not a nice-to-have.
Designing the model: see the scroll state machine
for a concrete way to make these principles hold together.
The 15 principles
Intent: move only when asked
Move only when the reader asked to move. If someone is reading, don't
pull them somewhere else. Auto-scroll is never the default — it is a response
to a signal that the reader wants to follow.
Follow only while they're following. If they're at the live edge, keep
the stream in view. The moment they scroll away, leave them there. Following
is a mode the reader enters and exits, not a permanent setting.
Every interaction is intent. Scrolling is not the only signal. Selecting
text, using the keyboard, opening a link, or searching all mean "I'm doing
something here" and must stop the interface from moving.
New turns: somewhere to be read from the beginning
Start a new turn near the top of the viewport. This gives the new turn
room it can be read from the start, instead of being born at the bottom edge.
Then stream in the answer. Once the turn is anchored, let the streaming
answer grow downward into the available space.
Keep part of the previous conversation in context. Enough of the prior
turn stays visible that the reader knows where they are. Context, not a hard
cut to a blank viewport.
Offscreen growth: don't disturb what's being read
Let new content arrive offscreen. The conversation can keep streaming
without changing what the reader is currently looking at.
Show what's happening out of view. Make it clear when a response is still
streaming below, or when new messages have arrived above/below the viewport.
Make it easy to return to the latest reply. A "Jump to latest" action
brings the reader back to the live edge and resumes following.
Navigation: let people go anywhere
Let people jump anywhere in the conversation. Long threads need message
links, search, unread markers, and direct navigation — not just scrolling.
Reopen where the reader left off. A saved conversation opens at the last
meaningful turn — usually the last user message — not the absolute bottom.
Stability: keep the reader's place
Keep the reader's place when layout changes. Images load, markdown
expands, code blocks render, older messages load in above. None of it should
make the reader lose their place. Anchor to a visible element and preserve
its position across reflow.
Handle interruptions without stealing position. Stopping, retrying,
regenerating, branching, and errors must not unexpectedly move the
conversation.
Quality: responsive and accessible
Stay responsive in long threads. Streaming text, markdown, code, images,
and long history should still feel responsive — virtualize, batch, and avoid
layout thrash so the thread never stutters.
Be accessible without the noise. Keep the transcript navigable, preserve
keyboard focus, and announce important events (streaming started/finished,
new messages) at a comfortable pace — informative, not a screen-reader storm.
A model that works
A reliable way to satisfy these principles is a small explicit state machine
rather than scattered scrollToBottom() calls.
following (boolean): are we pinned to the live edge? Start a stream
following = true only if the reader hasn't signalled otherwise.
Exit follow on intent: any of wheel/touch-scroll up, text selection,
keydown for navigation, focus entering a link/control, or opening search sets
following = false. (Principles 2, 3.)
Enter follow only deliberately: reaching the bottom by the reader's own
scroll, or clicking "Jump to latest", sets following = true. (Principles 1, 9.)
While streaming: if following, keep the live edge in view; if not, append
offscreen and surface an indicator instead. (Principles 7, 8.)
On new turn: scroll the new turn's top near the top of the viewport,
leaving a slice of the previous turn visible, then stream into the space
below. (Principles 4, 5, 6.)
On layout shift: before async content (images/markdown/code/history
prepend) changes height, capture an anchor element + offset; after, restore
it. Prefer the browser's scroll anchoring / overflow-anchor and only correct
manually where it can't reach. (Principle 12.)
On interruption: stop/retry/regenerate/branch/error must not call any
scroll method that isn't gated on following. (Principle 13.)
On open/restore: scroll to the last meaningful turn (typically the last
user message), not the bottom. (Principle 11.)
Common defects this prevents
Auto-scroll yanking the viewport while the reader scrolls up to re-read.
The "fighting the scrollbar" feeling where every token tick re-pins to bottom.
Losing your place when an image finally loads or a code block renders.
A regenerate/stop button silently teleporting you to the bottom.
Reopening a long thread dumped at the absolute end with no context.
Screen readers announcing every streamed chunk.
Review checklist
Walk this when reviewing or debugging a chat surface. Each item maps to the
principle in parentheses. A "no" is a defect against never move the reader
against their intent.
Reading mid-thread is never interrupted by auto-scroll. (1)
Scrolling to the live edge resumes following; scrolling away stops it. (2)
Selecting text / keyboard nav / opening a link / search all halt motion. (3)
A new turn anchors near the top of the viewport, not the bottom. (4, 5)
A readable slice of the previous turn stays visible on a new turn. (6)
New content can stream in offscreen without moving the viewport. (7)
An indicator shows streaming-below / new-messages out of view. (8)
"Jump to latest" returns to the live edge and resumes following. (9)
Message links, search, unread markers, and direct navigation exist. (10)
Reopening lands on the last meaningful turn (last user message), not bottom. (11)
Image load, markdown/code render, and history prepend preserve place. (12)