NavigationBack to top
Back to top
A floating arrow-up button that appears in the bottom-right after 1,200 px of scroll. Smooth-scrolls to the top.
Demo
The button is 44 × 44 px, fixed to the bottom-right, with a subtle shadow. It is hidden until the user has scrolled past 1,200 px.
Default
Anatomy
- 44 × 44 px circle,
--foregroundbackground,--backgroundicon - Fixed bottom-right, 16 px from the edges on mobile, 24 px on desktop
- Shadow:
elevation-2 - Appears after 1,200 px of scroll, with a 200 ms ease-out fade-in
Implementation
back-to-top.tsx
"use client"
import { useEffect, useState } from "react"
import { ArrowUp } from "lucide-react"
import SiteIcon from "@/components/site-icon"
interface BackToTopProps {
threshold?: number
smooth?: boolean
}
export function BackToTop({ threshold = 1200, smooth = true }: BackToTopProps) {
const [visible, setVisible] = useState(false)
useEffect(() => {
const onScroll = () => setVisible(window.scrollY > threshold)
onScroll()
window.addEventListener("scroll", onScroll, { passive: true })
return () => window.removeEventListener("scroll", onScroll)
}, [threshold])
return (
<button
type="button"
className={`back-to-top ${visible ? "back-to-top--visible" : ""}`}
onClick={() => window.scrollTo({ top: 0, behavior: smooth ? "smooth" : "auto" })}
aria-label="Back to top"
>
<SiteIcon icon={ArrowUp} size="md" />
</button>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
threshold | number | 1200 | Show after this many px of scroll |
smooth | boolean | true | Smooth scroll vs instant |