Scroll Behavior
SvelteVirtualChat has two scroll states: following bottom and scrolled away. The component transitions between them automatically based on the user’s scroll position.
Follow-Bottom
When the viewport is within followBottomThresholdPx (default 48px) of the bottom:
- New messages automatically scroll into view
- Height changes from streaming snap the viewport to bottom
isFollowingBottomistrue
Scrolled Away
When the user scrolls up past the threshold:
- New messages are added to the array but the viewport does not move
- Streaming height changes do not affect the scroll position
isFollowingBottomisfalse
Detecting State Changes
Use onFollowBottomChange to react to transitions:
<script lang="ts">
import SvelteVirtualChat from '@humanspeak/svelte-virtual-chat'
let isFollowing = $state(true)
let unreadCount = $state(0)
let chat: ReturnType<typeof SvelteVirtualChat>
</script>
<SvelteVirtualChat
bind:this={chat}
onFollowBottomChange={(following) => {
isFollowing = following
if (following) unreadCount = 0
}}
...
/>
{#if !isFollowing && unreadCount > 0}
<button onclick={() => chat.scrollToBottom({ smooth: true })}>
{unreadCount} new messages — click to scroll down
</button>
{/if}<script lang="ts">
import SvelteVirtualChat from '@humanspeak/svelte-virtual-chat'
let isFollowing = $state(true)
let unreadCount = $state(0)
let chat: ReturnType<typeof SvelteVirtualChat>
</script>
<SvelteVirtualChat
bind:this={chat}
onFollowBottomChange={(following) => {
isFollowing = following
if (following) unreadCount = 0
}}
...
/>
{#if !isFollowing && unreadCount > 0}
<button onclick={() => chat.scrollToBottom({ smooth: true })}>
{unreadCount} new messages — click to scroll down
</button>
{/if}Tuning the Threshold
The followBottomThresholdPx prop controls the sensitivity:
<!-- More sensitive (follows even when slightly above bottom) -->
<SvelteVirtualChat followBottomThresholdPx={100} ... />
<!-- Less sensitive (must be very close to bottom) -->
<SvelteVirtualChat followBottomThresholdPx={10} ... /><!-- More sensitive (follows even when slightly above bottom) -->
<SvelteVirtualChat followBottomThresholdPx={100} ... />
<!-- Less sensitive (must be very close to bottom) -->
<SvelteVirtualChat followBottomThresholdPx={10} ... />Bottom Gravity
When messages don’t fill the viewport (e.g., a new conversation with 2 messages), they sit at the bottom of the viewport — not the top. This matches the behavior of every major chat application.
As more messages are added and exceed the viewport height, normal scrolling takes over.
Return to Bottom
Use the imperative API to bring the user back:
// Instant jump
chat.scrollToBottom()
// Smooth animation
chat.scrollToBottom({ smooth: true })// Instant jump
chat.scrollToBottom()
// Smooth animation
chat.scrollToBottom({ smooth: true })After returning, isFollowingBottom becomes true again and new messages will auto-scroll.