Back to catalog
Component detail entry
Data Display
@vean/ui
SBacktop

Backtop

Backtop belongs to the Data Display category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Backtop

Overview

SBacktop reveals a floating button after the scroll target passes a configurable threshold and smoothly scrolls that target back to the top when activated. It wraps SButton with scroll-position tracking, requestAnimationFrame-based smooth scrolling, and prefers-reduced-motion support. Use it to let users quickly return to the top of long pages or scrollable containers.

Note: In addition to SBacktop, the Aria layer also exports Backtop for custom composition.

Usage

Features

  • 📏 Visibility threshold — The button appears only after scrolling past visibilityHeight pixels (default 400).
  • 🎬 Smooth animation — Scrolls to top with an easeInOutCubic easing over duration ms (default 300). Set duration={0} for instant scroll.
  • ♿ Reduced motion — Respects prefers-reduced-motion: reduce; skips animation and scrolls instantly when the user prefers reduced motion.
  • 🎯 Flexible target — target accepts window (default), an HTMLElement, a Ref<HTMLElement>, or a CSS selector string.
  • 🔧 Aria composition — The Aria Backtop is exported separately for custom button styling; SBacktop provides preset buttonVariants + fixed positioning.
  • 🎨 Full button props — Inherits all ButtonProps (color, size, variant, shape, shadow, disabled, etc.) plus icon/iconClass/iconProps for the default icon.
  • 📡 Events — Emits change (visibility toggled) and click (button clicked).
  • 🌐 SSR-safe — Guards all browser APIs (window, document, matchMedia); renders without errors on the server.

Demos

Basic

Scroll inside the container to reveal the Backtop button.

Target

Backtop can observe a selector target and render custom content.

Custom Styling

Use button style props, slot content, and custom positioning classes.

API

Aria Layer

1

Backtop

17 Props2 Emits
Props
PropTypeDefaultDescription
class
ClassValue
—
Additional class names applied to the root element.
color
ThemeColor
—
Theme color of the component.
size
ThemeSize
—
Visual size of the component.
variant
ButtonVariant
—
Visual variant of the component.
shape
ButtonShape
—
Shape of the component.
shadow
ButtonShadow
—
Shadow style of the component.
fitContent
boolean
—
Whether the component should fit its content width.
icon
string
'lucide:arrow-up'
The icon name of iconify.
iconClass
ClassValue
—
The class of the icon.
iconProps
Partial<IconProps>
—
The props of the icon.
visibilityHeight
number
400
Scroll distance that must be reached before the Backtop button becomes visible.
target
AffixTarget | null
window
Scroll target that Backtop listens to and scrolls.
duration
number
300
Duration of the scroll-to-top animation in milliseconds.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
Emits
Emit NameParametersDescription
change
boolean
Emitted when change occurs.
click
PointerEvent
Emitted when click occurs.

Notes

Architecture and benchmark differences

SBacktop splits into an Aria layer that owns scroll tracking, target resolution, animation, and visibility state, and a styled layer that owns the backtopVariants recipe (extends buttonVariants with fixed z-50 and size-based bottom-* end-* positioning). This follows the VeanUI Aria/styled separation pattern.

AspectVeanUIAnt Design BackTopElement Plus BacktopNaive UI BackTop
ArchitectureAria + styled splitstyled onlystyled onlystyled only
Smooth scrollingrequestAnimationFrame + easeInOutCubicrequestAnimationFramerequestAnimationFramerequestAnimationFrame
Reduced motion✅ prefers-reduced-motion———
Target typewindow / HTMLElement / Ref / CSS selectorHTMLElement / functionHTMLElement / stringHTMLElement / string
Visibility thresholdvisibilityHeight (number)visibilityHeight (number)visibilityHeight (number)visibilityHeight (number)
Animation durationduration (ms)———
Aria export✅ Backtop———
Disabled state✅ inherited from Button———

Runtime cautions

  • hidden attribute: When the button is not visible, the Aria layer sets hidden on the <button> element, which applies display: none. This prevents CSS transitions on show/hide. If you need fade transitions, override [hidden] { display: block; } and use opacity/visibility transitions in your custom class.
  • Focus management: When the button becomes hidden while focused (e.g., after scrolling to top), the Aria layer automatically blurs it to prevent focus being trapped on a hidden element.
  • Scroll listener cleanup: The Aria layer uses useEventListener with onWatcherCleanup to remove scroll listeners when the target changes or the component unmounts. No manual cleanup is needed.
  • target reactivity: Changing target or visibilityHeight at runtime triggers target re-resolution and a visibility re-check via nextTick.

FAQ

How do I target a specific scrollable container? Pass the element or a CSS selector: <SBacktop target="#my-scroll-container" /> or <SBacktop :target="scrollRef" />. The component resolves the target and listens to its scroll event.

How do I disable the smooth animation? Set duration={0}: <SBacktop :duration="0" />. The component also automatically skips animation when the user has prefers-reduced-motion: reduce enabled.

Can I use a custom button instead of the default? Yes. Import the Aria Backtop from @vean/aria/backtop and compose it with your own button:

<script setup lang="ts">
import { Backtop } from '@vean/aria/backtop';
</script>

<template>
  <Backtop :visibility-height="200" class="my-custom-button">
    <MyIcon />
  </Backtop>
</template>

Why does the button disappear immediately after clicking? After scrolling to top, the scroll position drops below visibilityHeight, so the button hides. The Aria layer blurs the button before hiding it to avoid focus being trapped on a hidden element.

How do I change the default icon? Pass the icon prop: <SBacktop icon="lucide:chevron-up" />. Use iconClass for icon styling and iconProps for additional SIcon props.

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.19.0

2026-05-11

Compare release

Fix

emit click event in onClick function

Scope: backtopAuthors: soybeanfeView commitaf273

Fix

fix aria-hidden warning when click

Scope: backtopAuthors: soybeanfeView commit437fe

v0.18.0

2026-05-05

Compare release

Optimization

update size handling in backtopVariants and computed class

Scope: backtopAuthors: soybeanjsView commitfa0df

Optimization

update click event type from MouseEvent to PointerEvent for consistency

Scope: backtopAuthors: soybeanfe, CopilotView commit4666c