Back to Top
Floating button that appears when scrolling, allowing quick return to the page top
Overview
Back to Top provides a floating button that appears when users scroll down, allowing quick return to the page top. Perfect for long pages, documentation, and content-heavy sites.
Key Features
- Auto Show/Hide - Appears after scrolling threshold
- Smooth Scrolling - Configurable animation duration
- Positioning - Bottom-right, bottom-left, or custom
- Callbacks - onShow and onHide events
Basic Usage
const backToTop = Domma.elements.backToTop('#back-to-top', {
showAfter: 300,
duration: 600,
position: 'bottom-right'
});
Getting Started
Add a back to top button to your page in three simple steps
Step 1: Add Button Element
Create a button element with a class and unique ID:
<button id="back-to-top" class="back-to-top-btn">↑</button>
Step 2: Include Domma
Add Domma CSS and JavaScript to your page:
<!-- CSS -->
<link rel="stylesheet" href="dist/domma.css">
<link rel="stylesheet" href="dist/elements.css">
<!-- JavaScript -->
<script src="dist/domma.min.js"></script>
Step 3: Initialize the Button
Call Domma.elements.backToTop() to activate the button:
Domma.elements.backToTop('#back-to-top', {
showAfter: 300, // Show after scrolling 300px
duration: 500 // Scroll animation duration in ms
});
Note: The back to top button automatically shows/hides based on scroll position and smoothly animates scrolling to the top when clicked. The component handles all scroll event listeners and positioning.
Quick Start
Simple Back to Top Button
Scroll down this demo area to see the button appear
Scroll down...
Keep scrolling...
Almost there...
You should see the button now!
<p class="text-center text-muted mb-3">Scroll down this demo area to see the button appear</p>
<div class="demo-scroll-container" id="quick-demo-container" style="height: 400px; overflow-y: auto; border: 1px solid var(--dm-color-border, #e0e0e0); border-radius: 0.5rem; padding: 1.5rem; position: relative;">
<div style="min-height: 1200px;">
<p><strong>Scroll down...</strong></p>
<p class="mt-300">Keep scrolling...</p>
<p class="mt-300">Almost there...</p>
<p class="mt-200">You should see the button now!</p>
</div>
<button type="button" id="quick-back-to-top" class="btn btn-primary back-to-top-btn">↑</button>
</div>/**
* Simple Back to Top Button - from public/showcase/elements/back-to-top.
*/
export function mount(root) {
const quickBtn = E.backToTop(root.querySelector('#quick-back-to-top'), {
showAfter: 200,
duration: 500,
target: '#quick-demo-container'
});
}<button id="back-to-top" class="back-to-top-btn">↑</button>
<script>
Domma.elements.backToTop('#back-to-top', {
showAfter: 200,
duration: 500
});
</script>
Native Web Component
Modern Standard: BackToTop is now available as a native Web Component with Shadow DOM encapsulation. Use either the traditional API (above) or the native
<domma-back-to-top>tag below for better style isolation and framework compatibility.
Native Tag Syntax
Use the native <domma-back-to-top> Web Component directly in HTML with attributes for configuration:
<!-- Basic Web Component -->
<domma-back-to-top></domma-back-to-top>
<!-- Configured Web Component -->
<domma-back-to-top
show-after="400"
duration="500"
position="bottom-left"
offset="20"
></domma-back-to-top>
<!-- With Scroll Container -->
<domma-back-to-top
target="#scrollable-content"
show-after="300"
></domma-back-to-top>
Live Web Component Demo
Scroll down to see the native Web Component appear
Web Component Example
This uses <domma-back-to-top> tag
Shadow DOM provides style isolation
Reactive attribute updates supported
<p class="text-center text-muted mb-3">Scroll down to see the native Web Component appear</p>
<div class="demo-scroll-container" id="wc-demo-container" style="height: 400px; overflow-y: auto; border: 1px solid var(--dm-color-border, #e0e0e0); border-radius: 0.5rem; padding: 1.5rem; position: relative;">
<div style="min-height: 1200px;">
<p><strong>Web Component Example</strong></p>
<p class="mt-200">This uses <code><domma-back-to-top></code> tag</p>
<p class="mt-300">Shadow DOM provides style isolation</p>
<p class="mt-300">Reactive attribute updates supported</p>
</div>
</div>
<domma-back-to-top id="wc-demo-btn" show-after="200" duration="500" position="bottom-right" offset="16"></domma-back-to-top>/**
* Live Web Component Demo - from public/showcase/elements/back-to-top.
*/
export function mount(root) {
// Web Component Demos
// Main Web Component demo - get the element and set its target
const wcDemoBtn = $(root).find('#wc-demo-btn')[0];
if (wcDemoBtn) {
wcDemoBtn.setAttribute('target', '#wc-demo-container');
}
}Available Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
show-after |
Number | viewport height | Pixels to scroll before showing |
duration |
Number | 300 |
Scroll animation duration in ms |
position |
String | 'bottom-right' |
Position: bottom-right, bottom-left |
offset |
Number | 16 |
Distance from screen edge in px |
target |
String | window |
CSS selector for scroll container |
z-index |
Number | 1000 |
Z-index for stacking context |
visible |
Boolean | false |
Initial visibility state |
JavaScript API
Access the Web Component instance and call methods programmatically:
// Get the Web Component element
const btn = $('domma-back-to-top')[0];
// Call methods
btn.scroll(); // Scroll to top
btn.show(); // Show button immediately
btn.hide(); // Hide button
btn.toggle(); // Toggle visibility
btn.isVisible(); // Check visibility → boolean
btn.getButton(); // Get button element
// Update attributes programmatically
btn.setShowAfter(500); // Change threshold
btn.setPosition('bottom-left'); // Change position
btn.setOffset(24); // Change offset
// Listen for events
btn.addEventListener('show', (e) => {
console.log('Button appeared');
});
btn.addEventListener('hide', (e) => {
console.log('Button hidden');
});
Reactive Attributes Demo
Attributes update reactively!
Try the buttons above
<div class="flex gap-2 justify-center mb-3">
<button type="button" id="wc-change-position" class="btn btn-sm btn-outline">Toggle Position</button>
<button type="button" id="wc-change-offset" class="btn btn-sm btn-outline">Change Offset</button>
<button type="button" id="wc-manual-show" class="btn btn-sm btn-outline">Force Show</button>
</div>
<div class="demo-scroll-container" id="reactive-demo" style="height: 300px; overflow-y: auto; border: 1px solid var(--dm-color-border, #e0e0e0); border-radius: 0.5rem; padding: 1.5rem; position: relative;">
<div style="min-height: 800px;">
<p>Attributes update reactively!</p>
<p class="mt-300">Try the buttons above</p>
</div>
</div>
<domma-back-to-top id="reactive-btn" show-after="200" duration="400"></domma-back-to-top>/**
* Reactive Attributes Demo - from public/showcase/elements/back-to-top.
*/
export function mount(root) {
// Reactive attributes demo
const reactiveBtn = $(root).find('#reactive-btn')[0];
if (reactiveBtn) {
reactiveBtn.setAttribute('target', '#reactive-demo');
let currentPosition = 'bottom-right';
$(root).find('#wc-change-position').on('click', () => {
currentPosition = currentPosition === 'bottom-right' ? 'bottom-left' : 'bottom-right';
reactiveBtn.setPosition(currentPosition);
});
let currentOffset = 16;
$(root).find('#wc-change-offset').on('click', () => {
currentOffset = currentOffset === 16 ? 32 : 16;
reactiveBtn.setOffset(currentOffset);
});
$(root).find('#wc-manual-show').on('click', () => {
reactiveBtn.show();
});
}
}Event Handling
<domma-back-to-top id="my-btn"></domma-back-to-top>
<script>
const btn = $('#my-btn')[0];
// Listen for show event
btn.addEventListener('show', (e) => {
console.log('Button became visible');
$('#status')[0].textContent = 'Visible';
});
// Listen for hide event
btn.addEventListener('hide', (e) => {
console.log('Button became hidden');
$('#status')[0].textContent = 'Hidden';
});
</script>
Benefits of Web Components
Shadow DOM Isolation: Styles don't leak in or out Native Browser API: No framework required Reactive Attributes: Changes update automatically Framework Agnostic: Works with React, Vue, Angular, Svelte Custom Events: Standard DOM event system Backwards Compatible: Traditional API still available
Using with Frameworks
React
import { useRef, useEffect } from 'react';
function MyComponent() {
const btnRef = useRef(null);
useEffect(() => {
const btn = btnRef.current;
const handleShow = () => console.log('Visible');
btn.addEventListener('show', handleShow);
return () => btn.removeEventListener('show', handleShow);
}, []);
return <domma-back-to-top ref={btnRef} show-after="300" />;
}
Vue
<template>
<domma-back-to-top
ref="backToTop"
:show-after="300"
:duration="500"
@show="onShow"
@hide="onHide"
></domma-back-to-top>
</template>
<script>
export default {
methods: {
onShow() { console.log('Visible'); },
onHide() { console.log('Hidden'); }
},
mounted() {
this.$refs.backToTop.scroll();
}
};
</script>
Angular
import { Component, ViewChild, ElementRef } from '@angular/core';
@Component({
selector: 'app-my-component',
template: `
<domma-back-to-top
#backToTop
show-after="300"
(show)="onShow()"
(hide)="onHide()"
></domma-back-to-top>
`
})
export class MyComponent {
@ViewChild('backToTop') backToTop!: ElementRef;
onShow() { console.log('Visible'); }
onHide() { console.log('Hidden'); }
scrollToTop() {
this.backToTop.nativeElement.scroll();
}
}
CSS Part Customization
Customize Web Component styles using CSS ::part() selectors:
/* Target the button inside Shadow DOM */
domma-back-to-top::part(button) {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
width: 50px;
height: 50px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
domma-back-to-top::part(button):hover {
transform: translateY(-2px) scale(1.15);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
}
Tutorial
Build a back to top button with custom styling and callbacks.
Implementation Guide
Scroll down to see the custom back to top button with callbacks tracking visibility state...
Understanding Back to Top
The back to top button provides a quick way to return to the page start without manually scrolling.
When to Use
Best for long-form content, documentation pages, blog articles, and dashboards with extensive data.
Customization Options
Configure appearance threshold, animation duration, positioning, and event callbacks to match your design.
User Experience
The button automatically shows when scrolling past the threshold and hides when near the top of the page.
Button status:
<div class="demo-scroll-container" id="tutorial-container" style="height: 400px; overflow-y: auto; border: 1px solid var(--dm-color-border, #e0e0e0); border-radius: 0.5rem; position: relative;">
<div style="min-height: 1500px; padding: 1.5rem;">
<h3 class="text-2xl font-semibold mb-4">Implementation Guide</h3>
<p class="mb-6 text-gray-600">Scroll down to see the custom back to top button with callbacks tracking visibility state...</p>
<div class="mt-200">
<h4>Understanding Back to Top</h4>
<p>The back to top button provides a quick way to return to the page start without manually scrolling.</p>
</div>
<div class="mt-200">
<h4>When to Use</h4>
<p>Best for long-form content, documentation pages, blog articles, and dashboards with extensive data.</p>
</div>
<div class="mt-200">
<h4>Customization Options</h4>
<p>Configure appearance threshold, animation duration, positioning, and event callbacks to match your design.</p>
</div>
<div class="mt-200">
<h4>User Experience</h4>
<p>The button automatically shows when scrolling past the threshold and hides when near the top of the page.</p>
</div>
</div>
<button type="button" id="tutorial-back-to-top" class="btn btn-primary back-to-top-btn">
<span class="text-2xl">↑</span>
</button>
</div>
<div id="tutorial-status" class="mt-3 p-3 bg-surface rounded text-center">
<p class="text-muted text-sm">Button status: <span id="button-status">Hidden</span></p>
</div>/**
* Tutorial - from public/showcase/elements/back-to-top.
*/
export function mount(root) {
// Tutorial
const tutorialBtn = E.backToTop(root.querySelector('#tutorial-back-to-top'), {
showAfter: 300,
duration: 600,
target: '#tutorial-container',
onShow: () => {
$(root).find('#button-status')[0].textContent = 'Visible';
},
onHide: () => {
$(root).find('#button-status')[0].textContent = 'Hidden';
}
});
}const backToTop = Domma.elements.backToTop('#back-to-top', {
showAfter: 300,
duration: 600,
position: 'bottom-right',
offset: { bottom: 20, right: 20 },
target: '#scrollable-container',
onShow: () => {
console.log('Button shown');
$('#status')[0].textContent = 'Visible';
},
onHide: () => {
console.log('Button hidden');
$('#status')[0].textContent = 'Hidden';
}
});
Examples
Different Positions
Scroll to see buttons at different positions...
Bottom right button appears first
You should see the buttons now
<div class="flex gap-4 justify-center mb-3">
<button type="button" id="show-bottom-right" class="btn btn-outline btn-sm">Bottom Right</button>
<button type="button" id="show-bottom-left" class="btn btn-outline btn-sm">Bottom Left</button>
</div>
<div class="demo-scroll-container" id="position-demo" style="height: 300px; overflow-y: auto; border: 1px solid var(--dm-color-border, #e0e0e0); border-radius: 0.5rem; padding: 1.5rem; position: relative;">
<div style="min-height: 800px;">
<p>Scroll to see buttons at different positions...</p>
<p class="mt-200">Bottom right button appears first</p>
<p class="mt-300">You should see the buttons now</p>
</div>
<button type="button" id="btn-bottom-right" class="btn btn-primary back-to-top-btn">↑</button>
<button type="button" id="btn-bottom-left" class="btn btn-primary back-to-top-btn">↑</button>
</div>/**
* Different Positions - from public/showcase/elements/back-to-top.
*/
export function mount(root) {
// Position examples
const btnRight = E.backToTop(root.querySelector('#btn-bottom-right'), {
showAfter: 200,
target: '#position-demo',
offset: {bottom: 20, right: 20}
});
const btnLeft = E.backToTop(root.querySelector('#btn-bottom-left'), {
showAfter: 200,
target: '#position-demo',
offset: {bottom: 20, left: 20}
});
}Custom Duration
Try different scroll speeds...
Scroll down to see the button
<div class="demo-scroll-container" id="duration-demo" style="height: 300px; overflow-y: auto; border: 1px solid var(--dm-color-border, #e0e0e0); border-radius: 0.5rem; padding: 1.5rem; position: relative;">
<div style="min-height: 1000px;">
<p>Try different scroll speeds...</p>
<div class="flex gap-2 mt-4">
<button type="button" class="btn btn-sm btn-outline" data-action="1">Fast (200ms)</button>
<button type="button" class="btn btn-sm btn-outline" data-action="2">Slow (1000ms)</button>
</div>
<p class="mt-300">Scroll down to see the button</p>
</div>
<button type="button" id="duration-btn" class="btn btn-primary back-to-top-btn">↑</button>
</div>/**
* Custom Duration - from public/showcase/elements/back-to-top.
*/
export function mount(root) {
// Duration example
const durationBtn = E.backToTop(root.querySelector('#duration-btn'), {
showAfter: 200,
duration: 600,
target: '#duration-demo'
});
// Handlers the old page had inline (onclick=…), wired here.
$(root).find('[data-action="1"]').on('click', function (event) {
durationBtn.scroll(200);
});
$(root).find('[data-action="2"]').on('click', function (event) {
durationBtn.scroll(1000);
});
}Programmatic Control
Use buttons above to control the back to top button
Scroll position tracked
<div class="flex gap-2 justify-center mb-3">
<button type="button" id="prog-show" class="btn btn-outline btn-sm">Show</button>
<button type="button" id="prog-hide" class="btn btn-outline btn-sm">Hide</button>
<button type="button" id="prog-toggle" class="btn btn-outline btn-sm">Toggle</button>
<button type="button" id="prog-scroll" class="btn btn-outline btn-sm">Scroll to Top</button>
</div>
<div class="demo-scroll-container" id="programmatic-demo" style="height: 300px; overflow-y: auto; border: 1px solid var(--dm-color-border, #e0e0e0); border-radius: 0.5rem; padding: 1.5rem; position: relative;">
<div style="min-height: 800px;">
<p>Use buttons above to control the back to top button</p>
<p class="mt-600">Scroll position tracked</p>
</div>
<button type="button" id="programmatic-btn" class="btn btn-primary back-to-top-btn">↑</button>
</div>/**
* Programmatic Control - from public/showcase/elements/back-to-top.
*/
export function mount(root) {
// Programmatic control
const programmaticBtn = E.backToTop(root.querySelector('#programmatic-btn'), {
showAfter: 200,
target: '#programmatic-demo'
});
$(root).find('#prog-show').on('click', () => programmaticBtn.show());
$(root).find('#prog-hide').on('click', () => programmaticBtn.hide());
$(root).find('#prog-toggle').on('click', () => programmaticBtn.toggle());
$(root).find('#prog-scroll').on('click', () => programmaticBtn.scroll(400));
}Best Practices
Accessibility
- Keyboard Access - Ensure button is keyboard focusable
- ARIA Label - Add
aria-label="Back to top"for screen readers - Focus Visibility - Provide clear focus indicator
UX Guidelines
- Threshold - Show after 200-400px scroll for optimal UX
- Positioning - Bottom-right is conventional, but avoid blocking content
- Animation Duration - 400-800ms provides smooth but quick scrolling
- Visual Clarity - Use clear up arrow (↑) or icon
Performance
- Throttle Scroll Events - Component automatically throttles scroll listeners
- Destroy When Done - Call
destroy()on single-page apps when navigating
API Reference
| Option | Type | Default | Description |
|---|---|---|---|
showAfter |
Number | 300 |
Scroll pixels before showing button |
duration |
Number | 500 |
Scroll animation duration (ms) |
position |
String | 'bottom-right' |
Position: bottom-right, bottom-left |
offset |
Object | { bottom: 20, right: 20 } |
Offset from edges (px) |
target |
String/Element | window |
Scroll target (default: window) |
onShow |
Function | null |
Show callback |
onHide |
Function | null |
Hide callback |
Methods
| Method | Parameters | Description |
|---|---|---|
scroll(duration) |
duration (optional) | Scroll to top with optional custom duration |
show() |
- | Show button immediately |
hide() |
- | Hide button immediately |
toggle() |
- | Toggle button visibility |
isVisible() |
- | Check if button is visible |
getButton() |
- | Get button element |
destroy() |
- | Remove button and clean up |
Config Engine
$.setup({
'#back-to-top': {
component: 'backToTop',
options: {
showAfter: 400,
duration: 600,
position: 'bottom-right',
onShow: () => console.log('Button appeared'),
onHide: () => console.log('Button hidden')
}
}
});
CSS Customisation
Override these CSS variables to customise Back-to-Top appearance and match your design system.
| Variable | Default | Controls |
|---|---|---|
--dm-primary |
var(--dm-blue-600) |
Button background colour |
--dm-primary-hover |
var(--dm-blue-700) |
Button hover colour |
--dm-radius-full |
9999px |
Button shape (circular) |
--dm-shadow-md |
0 4px 6px... |
Button shadow |
Example Override
:root {
/* Square button */
--dm-radius-full: 0.5rem;
}
Full CSS Customisation Cheat-Sheet →
Related Elements
<div class="grid grid-cols-1 gap-4"><a href="/showcase/elements/navbar" class="card card-hover">
<div class="card-body">
<h3 class="card-title">Navbar</h3>
<p class="card-text">Sticky navigation for page sections</p>
</div>
</a>
<a href="/showcase/elements/breadcrumbs" class="card card-hover">
<div class="card-body">
<h3 class="card-title">Breadcrumbs</h3>
<p class="card-text">Navigation trail for deep content</p>
</div>
</a>
</div>