Designed with AI chat bots in mind, unofficial port of use-stick-to-bottom.
A lightweight Vue component and composable designed for AI chat applications to smoothly stick to the bottom of messages.
- 🪶 Zero runtime dependencies
- 📦 Tree-shakable, ESM build with type declarations
- 🪄 Smooth spring animation and instant mode
- 🚀 Works with ResizeObserver
pnpm add vue-stick-to-bottom
# or npm i / yarn add
<template>
<StickToBottom class="relative h-[50vh] w-full">
<Message v-for="m in messages" :key="m.id" :message="m" />
<ScrollToBottom />
</StickToBottom>
</template>
ScrollToBottom
:
<script setup lang="ts">
import { useStickToBottomContext } from 'vue-stick-to-bottom'
const { isAtBottom, scrollToBottom } = useStickToBottomContext()
</script>
<template>
<button v-if="!isAtBottom" @click="scrollToBottom()">↓</button>
</template>
<script setup lang="ts">
import { useStickToBottom } from 'vue-stick-to-bottom'
const { scrollRef, contentRef, isAtBottom, scrollToBottom } = useStickToBottom()
</script>
<template>
<div ref="scrollRef" style="overflow: auto; height: 50vh;">
<div ref="contentRef">
<Message v-for="m in messages" :key="m.id" :message="m" />
</div>
</div>
<button v-if="!isAtBottom" @click="scrollToBottom()">↓</button>
</template>
-
Component
StickToBottom
- Props
initial?: boolean | 'instant' | { damping?: number; stiffness?: number; mass?: number }
resize?: 'instant' | { damping?: number; stiffness?: number; mass?: number }
targetScrollTop?: (target: number, ctx: { scrollElement: HTMLElement; contentElement: HTMLElement }) => number
damping?: number
(default 0.7)stiffness?: number
(default 0.05)mass?: number
(default 1.25)anchor?: 'auto' | 'none'
(maps to CSS overflow-anchor)
- Props
-
Composable
useStickToBottom(options?)
- Returns
scrollRef
,contentRef
: attach to container and content nodesisAtBottom
,isNearBottom
,escapedFromLock
: reactive statesscrollToBottom(options?)
,stopScroll()
- Returns
- Smooth spring animation to approach bottom; instant mode supported.
- Resize-safe: maintains visual stability when content grows or shrinks.
- User escape: scrolling up cancels stickiness; near-bottom scrolling resumes it.
- Optional
overflow-anchor: none
to avoid browser scroll anchoring conflicts.
Run the built-in demo:
pnpm dev
This opens a playground showcasing smooth vs instant columns, a speed slider, a floating “scroll to bottom” control, and an external “Stop Scroll” button.