Components/Scroll

Scroll

`@better-scroll/scroll-bar` powered `TxScroll` container.

VerifiedSince 0.3.4

Usage

Scroll

Loading demo...

Best Practices

  • Prefer native mode for plain article or document scrolling where platform behavior is enough; use BetterScroll only when consistent scrollbars, wheel bridging, bounce, or pull plugins matter.
  • Keep scrollChaining=false for nested panels by default. Enable it only when the parent-child scroll handoff is intentional and tested.
  • Use noPadding when the child component owns its own spacing, especially virtualized lists, tables, and full-bleed media.
  • For horizontal or both-axis content, set a deterministic content width or allow the component to set width: max-content; otherwise BetterScroll cannot infer horizontal overflow reliably.
  • Always pair pullDownRefresh / pullUpLoad with the matching finish method after async work, including failure paths.
  • Avoid passing large mutable objects through options; prefer first-class props for documented behavior so watchers and docs stay accurate.

API Reference

Props

PropTypeDefaultDescription
nativebooleanfalseForce native browser scrolling and skip BetterScroll initialization.
unifiedbooleanfalseForce BetterScroll takeover for consistent cross-environment behavior (overrides Safari/Chromium auto-native; native=true still wins).
nativeAutoFallbackbooleantrueControls auto-native fallback on macOS + Chromium 145+; does not affect the macOS Safari native-first rule.
noPaddingbooleanfalseRemove the default content padding; horizontal and both-axis modes also set content width to max-content.
scrollChainingbooleanfalseAllow parent scroll handoff at boundaries; not recommended by default, enable only when nested handoff is explicitly needed.
direction'vertical' | 'horizontal' | 'both''vertical'Select the scroll axes; native mode maps this to overflow-x/y, BetterScroll maps it to scrollX, scrollY, and freeScroll.
scrollbarbooleantrueEnable the BetterScroll scrollbar plugin; native mode uses browser scrollbars.
scrollbarFadebooleantruePass BetterScroll scrollbar fade behavior through when scrollbar is enabled.
scrollbarInteractivebooleantrueAllow BetterScroll scrollbar dragging when scrollbar is enabled.
scrollbarAlwaysVisiblebooleanfalseKeep the BetterScroll wrapper in always-visible scrollbar state.
scrollbarMinSizenumber18Set the minimum BetterScroll scrollbar thumb size via --tx-scrollbar-min-size.
probeType0 | 1 | 2 | 33BetterScroll probeType
bouncebooleantrueEnable BetterScroll boundary bounce and the local wheel overshoot behavior.
clickbooleantruePass BetterScroll click handling through.
wheelbooleantrueEnable the local wheel bridge for BetterScroll mode; ctrl wheel gestures are ignored.
refreshOnContentChangebooleantrueObserve content mutations and call BetterScroll refresh() after changes.
pullDownRefreshboolean | Record<string, unknown>falseEnable pull-down refresh; BetterScroll receives plugin options, native mode emits a threshold-based trigger.
pullDownThresholdnumber70Minimum native touch delta and BetterScroll plugin threshold for pulling-down.
pullDownStopnumber56BetterScroll pull-down stop position; native mode does not use this value.
pullUpLoadboolean | Record<string, unknown>falseEnable pull-up load; BetterScroll receives plugin options, native mode emits when the bottom threshold is reached.
pullUpThresholdnumber0Native distance-to-bottom threshold and BetterScroll plugin threshold for pulling-up.
optionsRecord<string, unknown>{}Extra BetterScroll options; wheelOvershoot is consumed locally before options are passed through; on macOS, when wheel and bounce are both on, useTransition: false is injected by default — pass useTransition explicitly in options to override.

Events

EventParamsDescription
scroll{ scrollTop: number; scrollLeft: number }Emits absolute scroll offsets from native mode or BetterScroll position updates.
pulling-down-Emits once per pull-down cycle until finishPullDown() is called.
pulling-up-Emits once per pull-up cycle until finishPullUp() is called.

Slots

SlotDescription
defaultMain scroll content rendered inside .tx-scroll__content.
headerOptional content before the default slot. In native mode it is rendered before .tx-scroll__content; in BetterScroll mode it is rendered inside the scroll content.
footerOptional content after the default slot, commonly used for load-more status.

Expose

NameTypeDescription
nativeScrollRefRef<HTMLElement | null>Native scroll element ref when native mode is active.
scrollTo(x, y, time?)(x: number, y: number, time?: number) => voidScrolls to absolute offsets. BetterScroll mode negates offsets internally and honors time; native mode calls scrollTo(x, y).
getScrollInfo()() => TxScrollInfoReturns current offsets, scroll size, and client size.
refresh()() => voidCalls BetterScroll refresh() and updates scrollability state. No-op in native mode.
finishPullDown()() => voidResets native pull-down lock or forwards to BetterScroll finishPullDown() then schedules refresh.
finishPullUp()() => voidResets native pull-up lock or forwards to BetterScroll finishPullUp() then schedules refresh.

Behavior Notes

  • BetterScroll Mode
    • Supports bounce with a more consistent scrollbar appearance
    • Content/container changes auto refresh() (configurable via refreshOnContentChange)
  • Native Mode
    • Uses native browser scrolling
    • direction maps to overflow-x/y to keep structure consistent
    • macOS Safari uses native scrolling directly
    • Automatically falls back to native scrolling on macOS + Chromium 145+ (Chromium already supports it natively)
    • Set unified=true to force BetterScroll takeover across environments

Runtime Strategy (Priority)

  1. native=true: always use native scrolling (highest priority).
  2. unified=true: always let BetterScroll take over (consistent cross-environment behavior).
  3. Running on macOS Safari: use native scrolling directly.
  4. nativeAutoFallback=true and macOS + Chromium >= 145: auto switch to native scrolling.
  5. Otherwise: use BetterScroll.

Direction and Scrollbar

Scroll (horizontal)

Loading demo...

Scroll (bounce + always show scrollbar)

Loading demo...

Scroll Chaining (Advanced)

By default inner scrolling does not propagate to the outer container (even at edges). Enable scrollChaining if you want scroll to bubble at the top/bottom.

⚠️ We do not recommend enabling scrollChaining by default. In nested scrolling layouts, it can make users unsure which layer is actually scrolling. Enable it only when parent-child scroll handoff is explicitly required.

Scroll (scroll chaining, advanced)

Loading demo...

Use Native Scrolling

If you do not need BetterScroll behavior, switch to native scrolling (keeps the same container structure).

Scroll (native)

Loading demo...

Pull-to-Refresh and Load More

  • Pull-to-refresh: enable pullDownRefresh, listen to @pulling-down, then call finishPullDown() when done.
  • Load more: enable pullUpLoad, listen to @pulling-up, then call finishPullUp() when done.
  • In native=true or auto-native fallback mode, events are degraded triggers; pullDownStop only works in BetterScroll mode.

Scroll (pull down + pull up)

Loading demo...

Overview

  • native=true always wins. Otherwise, unified=true forces BetterScroll; macOS Safari and macOS Chromium with native overscroll support use native mode unless unified is set.
  • In native mode, direction maps to CSS overflow and scrollChaining=false maps to overscroll-behavior: contain on enabled axes.
  • In BetterScroll mode, direction maps to scrollX, scrollY, and freeScroll; probeType controls scroll event frequency.
  • Content and wrapper resize changes are coalesced into one animation frame before refresh(); refreshOnContentChange=false disables mutation-observer refreshes but keeps resize refreshes.
  • Pull-down / pull-up events are locked after emission. Consumers must call finishPullDown() / finishPullUp() after async work to allow the next cycle.
  • Native pull-down is a thresholded touch fallback at scrollTop 0; pullDownStop applies only to BetterScroll mode.

Technologies

  • Runtime contract: native=true always wins; otherwise unified=true forces BetterScroll, while macOS Safari and supported macOS Chromium default to native fallback.
  • Axis contract: native mode maps direction to CSS overflow and overscroll-behavior; BetterScroll maps it to scrollX, scrollY, and freeScroll.
  • Refresh contract: resize and content mutations are coalesced before refresh(). Pull-down/up events are lock-based and require finishPullDown() / finishPullUp() after async work.
  • Verified coverage: scroll.test.ts covers native overflow, slots, scroll events, getScrollInfo(), scrollTo(), native pull locks, and coalesced refreshes; scroll-export.test.ts protects the public export boundary.
  • Component source: packages/tuffex/packages/components/src/scroll/src/TxScroll.vue.
  • Runtime helpers: packages/tuffex/packages/components/src/scroll/src/scroll-wheel.ts, better-scroll-pull-plugins.ts, and runtime-capabilities.ts.
  • Types: packages/tuffex/packages/components/src/scroll/src/types.ts.
  • Coverage: packages/tuffex/packages/components/src/scroll/__tests__/scroll.test.ts verifies native direction overflow, slots, scroll events, getScrollInfo(), scrollTo(), native pull locks, and coalesced BetterScroll refreshes. scroll-export.test.ts verifies the public export boundary.
查看源码
packages/tuffex/packages/components/src/scroll/index.ts