PXD

useStickToBottom

Keep a scroll container pinned to the bottom while content changes, until the user scrolls away. Returning to the bottom re-enables auto-follow.

Auto-scroll is always instant. Smooth scrolling is intentionally unsupported: animation frames re-measure mid-scroll, flip isAtBottom off, and break continuous follow in chat-style lists.

Exports

function useStickToBottom(
  container: MaybeRefOrGetter<Nullable<HTMLElement>>,
  content?: MaybeRefOrGetter<Nullable<HTMLElement>>,
  options?: UseStickToBottomOptions,
): UseStickToBottomReturn

Types

interface UseStickToBottomOptions {
  /** Pixel distance from the bottom considered "at bottom". @default 8 */
  threshold?: MaybeRefOrGetter<number>
  /** Whether content updates should auto-scroll while at bottom. @default true */
  enabled?: MaybeRefOrGetter<boolean>
}

interface UseStickToBottomReturn {
  isAtBottom: ShallowRef<boolean>
  scrollToBottom: () => void
  forceStickToBottom: () => void
  stickIfNeeded: () => void
  update: () => void
}

Params

NameTypeDescription
containerMaybeRefOrGetter<Nullable<HTMLElement>>The scrollable container element
contentMaybeRefOrGetter<Nullable<HTMLElement>>Optional content root for ResizeObserver (falls back to container)
options.thresholdMaybeRefOrGetter<number>Distance from bottom considered "at bottom"
options.enabledMaybeRefOrGetter<boolean>Whether updates auto-scroll while at bottom

MutationObserver watches container (its subtree covers in-container content). Pass content when the measured content root is a distinct child that should drive ResizeObserver.

Returns

NameTypeDescription
isAtBottomShallowRef<boolean>Whether the container is currently within the bottom threshold
scrollToBottom() => voidInstantly scroll the container to the bottom (Y axis only)
forceStickToBottom() => voidScroll to bottom and re-enable auto-stick
stickIfNeeded() => voidScroll to bottom only when currently at bottom and enabled
update() => voidRe-measure whether the container is at the bottom

Usage

import { useStickToBottom } from 'pxd/composables'

const containerRef = shallowRef<HTMLElement>()
const contentRef = shallowRef<HTMLElement>()

const { isAtBottom, scrollToBottom, forceStickToBottom, stickIfNeeded, update } =
  useStickToBottom(containerRef, contentRef, {
    threshold: 8,
    enabled: true,
  })

The container must have a constrained height (explicit height, flex child with min-h-0, etc.). Otherwise it grows with content and never scrolls.

Source

Source