cd /news/ai-products/your-ai-chat-scrolls-wrong-fix-it-in… · home › topics › ai-products › article
[ARTICLE · art-161515] src=markodenic.tech ↗ pub= topic=ai-products verified=true sentiment=· neutral

Your AI chat scrolls wrong. Fix it in 4 lines of CSS

A tutorial published by developer Marko Denic shows that an AI chat box can follow a streaming answer without JavaScript scroll hacks by setting the container to `display: flex` with `flex-direction: column-reverse`, `overflow-y: auto` and `overscroll-behavior: contain`, then deleting the `scrollTop = scrollHeight` line. The `column-reverse` direction makes the bottom of the box the resting position, so new streamed text stays in view, while the browser's scroll anchoring holds the user's place when they scroll up; a single `.messages` wrapper keeps DOM order intact for screen readers and the Tab key. The technique relies on scroll anchoring, which the article says works in Chrome, Edge, Firefox and Safari 27, and requires one JavaScript line, `chat.scrollTop = 0`, to jump to the bottom when a new message is sent.

by read4 min views4 publishedOct 31, 2026
Your AI chat scrolls wrong. Fix it in 4 lines of CSS
Image: Markodenic (auto-discovered)

AI Coding Faster, Shipping Slower?

Explore the 2026 State of DevEx Report with industry leaders

Sponsor this newsletter · reach 9,500+ active developers

You’ve streamed the answer word by word, and it looks great until the answer gets longer than the chat box. Then one of two things happens. Either the text keeps streaming below the fold and the user has to keep scrolling down to read it, or you “fix” that with this:

output.textContent += value;
chat.scrollTop = chat.scrollHeight;

Now the box follows the answer, but it also yanks the user back to the bottom every time a new word arrives, even while they’re scrolling up to reread something. So you add a check for “is the user near the bottom?”, tune a pixel threshold, and it still flickers.

The browser can do all of this on its own. You just have to flip the box upside down.

The fix #

<div class="chat">
  <div class="messages">
    <!-- your messages, in normal order -->
  </div>
</div>
.chat {
  display: flex;
  flex-direction: column-reverse;
  overflow-y: auto;
  overscroll-behavior: contain;
}

Then delete the scrollTop = scrollHeight line. That’s it.

Click “Ask”, then scroll up while the answer is still streaming.

Why this works #

A normal scroll box rests at the top. When content grows, you stay at the top, and the new stuff piles up out of view.

column-reverse moves the start of the box to the bottom. Now the bottom is the resting position, so while the answer grows, you stay at the bottom and the newest line is always in view.

The moment the user scrolls up, the browser’s scroll anchoring takes over: it picks the line they’re looking at and keeps it in place while the answer keeps growing below. No threshold, no flicker, nothing dragging them back down.

What each line does #

  • display: flex: makes the box a flex container, so flex-direction applies.
  • flex-direction: column-reverse: puts the start of the scroll area at the bottom. This is the line that does the following.
  • overflow-y: auto: makes it a scroll box.
  • overscroll-behavior: contain: when the user scrolls to the top of the conversation, the page behind it stays put. This is thescroll chaining fix , and every chat box needs it.

Why the wrapper matters #

column-reverse reverses the order of the box’s children. Put your messages straight inside .chat and the oldest one ends up at the bottom.

With one .messages wrapper, the box only has one child to reverse. Your messages keep their normal order on screen, and the visual order matches the DOM. That matters, because screen readers and the Tab key follow the DOM, not what’s on screen.

The one line of JavaScript you still need #

When the user sends a new message, take them to the bottom even if they had scrolled up:

chat.scrollTop = 0;

Yes, 0. In a column-reverse box, 0 is the bottom, and scrollTop goes negative as you scroll up. Remember that when you add a “Jump to latest” button:

chat.addEventListener('scroll', () => {
  jumpButton.hidden = chat.scrollTop > -50;
});

jumpButton.addEventListener('click', () => {
  chat.scrollTo({ top: 0, behavior: 'smooth' });
});

Where this comes up #

  • AI chat and “Ask AI” boxes: answers that stream in for 20 seconds.
  • Support chat widgets: new messages arrive while the user reads old ones.
  • Live logs and build output: follow the tail, stop when someone scrolls up to read an error.
  • Comment and activity feeds: anything where the newest item goes at the bottom.

The limits #

  • Browser support: following the answer works everywhere. Staying put when the user scrolls up relies on scroll anchoring, which works in Chrome, Edge, Firefox and Safari 27. In older Safari, the text the user is reading drifts up while the answer streams.
  • Negative scrollTop: any existing code that reads scrollTop on this box needs updating, since the values are now0 and below.
  • Short conversations sit at the bottom: the first message appears at the bottom of the box, like in a messaging app, not at the top.

Why this matters #

  • It’s what users expect: every chat app they use behaves exactly like this.
  • Less code: no scroll math on every chunk, no “near the bottom” check, no threshold to tune.
  • It can’t fight the user: the browser decides when to follow, based on where the user actually is.

Open your chat component, search for scrollHeight, and replace that line with these 4 lines of CSS.

Happy coding!

Marko

── more in #ai-products 4 stories · sorted by recency
── more on @marko denic 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/your-ai-chat-scrolls…] indexed:0 read:4min 2026-10-31 · —