ScrollToTopButton Component
· 3 min read
This component adds a fixed floating Back to Top button. It becomes visible after the user scrolls 300px vertically; on click it triggers a smooth scroll to the top while playing a short visual animation on the icon. It does not expose public props: customization (threshold, image) is done by editing the source (index.js
). The goal is to keep it lightweight and easy to reuse.
Overview
Implemented features:
- Appears after 300px scroll (hard‑coded condition)
- Smooth scroll to top on click
- CSS animation on click (
fly
+@keyframes flyUp
) - Show/Hide using opacity + visibility
- Scroll listener with cleanup in
useEffect
- Icon image can be swapped by changing the import
Component Code
src/components/ScrollToTopButton/index.js
import React, { useState, useEffect } from "react";
import clsx from "clsx";
import styles from "./styles.module.css";
import buttontop from '@site/static/img/buttontop.PNG'
export default function ScrollToTopButton() {
const [isVisible, setIsVisible] = useState(false);
const [fly, setFly] = useState(false);
useEffect(() => {
const toggleVisibility = () => {
if (window.scrollY > 300) {
setIsVisible(true);
} else {
setIsVisible(false);
}
};
window.addEventListener("scroll", toggleVisibility);
return () => window.removeEventListener("scroll", toggleVisibility);
}, []);
const scrollToTop = () => {
setFly(true);
window.scrollTo({ top: 0, behavior: "smooth" });
setTimeout(() => setFly(false), 800);
};
return (
<div
className={clsx(
styles.scrollBtn,
isVisible && styles.show,
fly && styles.fly
)}
onClick={scrollToTop}
>
<img
src={buttontop}
alt="Retour en haut"
width="30"
height="30"
/>
</div>
);
}
src/components/ScrollToTopButton/styles.module.css
.scrollBtn {
position: fixed;
bottom: 30px;
right: 30px;
width: 60px;
height: 60px;
cursor: pointer;
opacity: 0;
visibility: hidden;
transition: opacity 0.4s, visibility 0.4s;
z-index: 1000;
}
.scrollBtn img {
width: 100%;
height: 100%;
border-radius: 50%;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
transition: transform 0.3s;
}
.scrollBtn:hover img {
transform: scale(1.1);
}
/* Bouton visible après scroll */
.scrollBtn.show {
opacity: 1;
visibility: visible;
}
/* Animation "vol vers le haut" */
.scrollBtn.fly img {
animation: flyUp 0.8s ease-in forwards;
}
@keyframes flyUp {
0% {
transform: translateY(0) scale(1);
opacity: 1;
}
100% {
transform: translateY(-300px) scale(0.6);
opacity: 0;
}
}
Installation
- Copy the
ScrollToTopButton
folder intosrc/components/
- Import the component in your global layout (or a specific page)
- Ensure the image import works (
/static/img/buttontop.PNG
) - (Optional) Replace the image with your own
File structure
src/components/ScrollToTopButton/
├── index.js # Main React component
└── styles.module.css # Scoped CSS Module
Configuration
- Threshold: edit
if (window.scrollY > 300)
inindex.js
- Image: replace the imported
buttontop
image
Customization
Change the image
- Place your image inside
static/img/
- Update the import in
index.js
:
import buttontop from '@site/static/img/your-image.png'
- The component uses it like:
<img
src={buttontop}
alt="Back to top"
width="30"
height="30"
/>
Edit styles
Open styles.module.css
and adjust:
- Position: tweak
bottom
/right
- Size: adjust
width
/height
- Visual: modify
box-shadow
- Animation: change
flyUp
keyframes
State & Behavior
isVisible
: true whenwindow.scrollY > 300
, else falsefly
: toggled to true on click, reset after 800ms- Scroll listener: handles visibility logic and is cleaned up on unmount
Animations
Show/Hide
transition: opacity 0.4s, visibility 0.4s;
Click animation (flyUp)
@keyframes flyUp {
0% {
transform: translateY(0) scale(1);
opacity: 1;
}
100% {
transform: translateY(-300px) scale(0.6);
opacity: 0;
}
}
Full example
import React from 'react';
import Layout from '@theme-original/Layout';
import ScrollToTopButton from '@site/src/components/ScrollToTopButton';
export default function LayoutWrapper(props) {
return (
<>
<Layout {...props} />
<ScrollToTopButton />
</>
);
}
This article is part of the Design your site series:
Like, share or comment on BlueSky
Loading comments…
Related posts

Component Avatar
August 29, 2025

Component Columns
September 3, 2025

Component ImageOnClick
September 5, 2025