
This tutorial shows how to add a floating “Back to Top” button that sticks to the bottom of the screen
and follows the mouse horizontally. It fades in after you scroll down and scrolls smoothly back to the top on click.
We’ll build it with minimal CSS and vanilla JavaScript.
Reference demo file: Back to Top button that follows mouse X
1) HTML — Add the button
Add this near the end of your page, just before </body>:
<button id="backToTop" aria-label="Back to top" title="Back to top">▲</button>
You can replace the ▲ with an SVG chevron if you want sharper visuals.
2) CSS — Fixed bottom, dark theme styling, and show/hide
Core styles. The button starts hidden and fades in when we add the .show class.
/* Floating Back to Top Button */
#backToTop{
position: fixed;
left: 18px; /* JS updates this to follow the mouse X */
bottom: 18px; /* Always sticks to the bottom */
width: 48px;
height: 48px;
border-radius: 24px;
border: 1px solid #2a2a2b;
background: #1b1b1c;
color: #e8e8e8;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
box-shadow: 0 8px 24px rgba(0,0,0,0.35);
opacity: 0; /* Hidden until scrolled down */
visibility: hidden;
transform: translateY(10px);
transition: opacity .25s ease, transform .25s ease, visibility .25s ease,
background .2s ease, color .2s ease, border-color .2s ease;
z-index: 1000;
user-select: none;
}
#backToTop:hover{ background: #2a2a2b; border-color: #3a3a3b; }
#backToTop.show{ opacity: 1; visibility: visible; transform: translateY(0); }
Optional: add a slight ease on horizontal movement too:
#backToTop{ transition: left .12s ease-out, opacity .25s, transform .25s, visibility .25s; }
3) JavaScript — Show on scroll, follow mouse X, smooth scroll to top
Place this script after the button (or enqueue it in your theme, making sure it runs after the button exists in the DOM):
(function(){
const btn = document.getElementById('backToTop');
if(!btn) return;
// Fade in/out based on scroll position
const toggle = () => {
const y = window.scrollY || document.documentElement.scrollTop;
if(y > 300){ btn.classList.add('show'); } else { btn.classList.remove('show'); }
};
window.addEventListener('scroll', toggle, { passive: true });
window.addEventListener('load', toggle);
// Smooth scroll to top on click
btn.addEventListener('click', (e) => {
e.preventDefault();
window.scrollTo({ top: 0, behavior: 'smooth' });
});
// Follow the mouse in the X dimension (clamped within viewport)
let rafPending = false;
let lastX = null;
const margin = 18; // match CSS
const applyX = () => {
rafPending = false;
if(lastX == null) return;
const btnWidth = btn.offsetWidth || 48;
const minX = margin;
const maxX = Math.max(minX, window.innerWidth - btnWidth - margin);
const target = Math.min(maxX, Math.max(minX, lastX - btnWidth / 2));
btn.style.left = target + 'px';
};
const onMove = (e) => {
lastX = e.clientX;
if(!rafPending){
rafPending = true;
requestAnimationFrame(applyX);
}
};
window.addEventListener('mousemove', onMove, { passive: true });
window.addEventListener('resize', () => { if(lastX != null){ applyX(); } });
})();
4) WordPress integration tips
- Where to put HTML: Add the button in your theme’s
footer.phpjust before</body>, or via a custom HTML block on pages where you want it. - Where to put CSS: Add to your theme stylesheet, Customizer Additional CSS, or a site-wide CSS file.
- Where to put JS: Enqueue a small JS file in your theme (recommended), or add a Custom HTML block with a
<script>tag at the bottom of the page. - Accessibility: Keep the
aria-labelandtitleattributes. Ensure color contrast passes your theme’s standards. - Performance: The code uses
passivelisteners andrequestAnimationFrameto keep it smooth.
5) Customization ideas
- Icon: Replace ▲ with an SVG chevron.
- Threshold: Change
y > 300to show the button earlier or later. - Size/spacing: Adjust
width,height, andbottom/margin. - Shadow/elevation: Increase/decrease box-shadow to match your design.
- Snap to edges: Modify the clamping logic to “snap” to left/right edges when close.
That’s it! You now have a polished floating “Back to Top” button that follows the mouse in the X direction, stays docked to the bottom, fades in after scrolling, and scrolls smoothly to the top.
