{"slug": "your-ai-chat-scrolls-wrong-fix-it-in-4-lines-of-css", "title": "Your AI chat scrolls wrong. Fix it in 4 lines of CSS", "summary": "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.", "body_md": "# Your AI chat scrolls wrong. Fix it in 4 lines of CSS\n\n**AI Coding Faster, Shipping Slower?**\n\nExplore the 2026 State of DevEx Report with industry leaders\n\n[Sponsor this newsletter · reach 9,500+ active developers](https://markodenic.tech/sponsorship/)\n\nYou’ve [streamed the answer word by word](https://markodenic.tech/stream-ai-answers-word-by-word-in-15-lines/), 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:\n\n```\noutput.textContent += value;\nchat.scrollTop = chat.scrollHeight;\n```\n\nNow 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.\n\nThe browser can do all of this on its own. You just have to flip the box upside down.\n\n## The fix\n\n```\n<div class=\"chat\">\n  <div class=\"messages\">\n    <!-- your messages, in normal order -->\n  </div>\n</div>\n.chat {\n  display: flex;\n  flex-direction: column-reverse;\n  overflow-y: auto;\n  overscroll-behavior: contain;\n}\n```\n\nThen delete the `scrollTop = scrollHeight` line. That’s it.\n\nClick “Ask”, then scroll up while the answer is still streaming.\n\n## Why this works\n\nA normal scroll box rests at the top. When content grows, you stay at the top, and the new stuff piles up out of view.\n\n`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.\n\nThe 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.\n\n## What each line does\n\n- **`display: flex`:** makes the box a flex container, so` flex-direction` applies.\n- **`flex-direction: column-reverse`:** puts the start of the scroll area at the bottom. This is the line that does the following.\n- **`overflow-y: auto`:** makes it a scroll box.\n- **`overscroll-behavior: contain`:** when the user scrolls to the top of the conversation, the page behind it stays put. This is the[scroll chaining fix](https://markodenic.tech/how-to-stop-a-modal-from-scrolling-the-page-behind-it/) , and every chat box needs it.\n\n## Why the wrapper matters\n\n`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.\n\nWith 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.\n\n## The one line of JavaScript you still need\n\nWhen the user sends a new message, take them to the bottom even if they had scrolled up:\n\n```\nchat.scrollTop = 0;\n```\n\nYes, `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:\n\n``` js\nchat.addEventListener('scroll', () => {\n  jumpButton.hidden = chat.scrollTop > -50;\n});\n\njumpButton.addEventListener('click', () => {\n  chat.scrollTo({ top: 0, behavior: 'smooth' });\n});\n```\n\n## Where this comes up\n\n- **AI chat and “Ask AI” boxes:** answers that stream in for 20 seconds.\n- **Support chat widgets:** new messages arrive while the user reads old ones.\n- **Live logs and build output:** follow the tail, stop when someone scrolls up to read an error.\n- **Comment and activity feeds:** anything where the newest item goes at the bottom.\n\n## The limits\n\n- **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.\n- **Negative `scrollTop`:** any existing code that reads` scrollTop` on this box needs updating, since the values are now`0` and below.\n- **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.\n\n## Why this matters\n\n- **It’s what users expect:** every chat app they use behaves exactly like this.\n- **Less code:** no scroll math on every chunk, no “near the bottom” check, no threshold to tune.\n- **It can’t fight the user:** the browser decides when to follow, based on where the user actually is.\n\nOpen your chat component, search for `scrollHeight`, and replace that line with these 4 lines of CSS.\n\nHappy coding!\n\nMarko", "url": "https://wpnews.pro/news/your-ai-chat-scrolls-wrong-fix-it-in-4-lines-of-css", "canonical_source": "https://markodenic.tech/your-ai-chat-scrolls-wrong-fix-it-in-4-lines-of-css/", "published_at": "2026-10-31 12:23:04+00:00", "updated_at": "2026-10-31 12:49:44.481026+00:00", "lang": "en", "topics": ["ai-products", "developer-tools", "generative-ai"], "entities": ["Marko Denic", "Chrome", "Edge", "Firefox", "Safari 27"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/your-ai-chat-scrolls-wrong-fix-it-in-4-lines-of-css", "markdown": "https://wpnews.pro/news/your-ai-chat-scrolls-wrong-fix-it-in-4-lines-of-css.md", "text": "https://wpnews.pro/news/your-ai-chat-scrolls-wrong-fix-it-in-4-lines-of-css.txt", "jsonld": "https://wpnews.pro/news/your-ai-chat-scrolls-wrong-fix-it-in-4-lines-of-css.jsonld"}}