scroll-progress-button
Інтерактив·Шаблон: Davies - Personal Portfolio HTML Template·Складність анімації: subtle·Адаптивний: Так

Файли-джерела
- index.html
button#goTop
Бібліотеки
jquery
Summary
Floating bottom-right "Go to top" button with a circular progress ring that fills as the user scrolls. Inside the ring is a chevron icon. The ring is drawn with a conic-gradient whose angle is updated from JS based on scroll percentage.
HTML structure (minimal)
<button id="goTop">
<span class="border-progress"></span>
<span class="ic-wrap">
<span class="icon icon-arrow-caret-right"></span>
</span>
</button>
Key SCSS tokens
#goTop {
position: fixed;
right: 24px;
bottom: 24px;
width: 56px; height: 56px;
border-radius: 50%;
background: var(--white);
border: 0;
z-index: 100;
opacity: 0;
transform: translateY(20px);
transition: opacity 0.3s ease, transform 0.3s ease;
&.show {
opacity: 1;
transform: translateY(0);
}
.border-progress {
position: absolute;
inset: -3px;
border-radius: 50%;
background: conic-gradient(var(--primary) var(--progress, 0deg), transparent 0);
-webkit-mask: radial-gradient(circle at center, transparent 28px, #000 28px);
mask: radial-gradient(circle at center, transparent 28px, #000 28px);
}
.ic-wrap .icon { transform: rotate(-90deg); }
}
Animation logic
// assets/js/main.js — goTop()
$(window).on('scroll', function () {
var scrollTop = $(window).scrollTop();
var docHeight = $(document).height() - $(window).height();
var scrollPercent = (scrollTop / docHeight) * 100;
var progressAngle = (scrollPercent / 100) * 360;
$borderProgress.css('--progress', progressAngle + 'deg');
if (scrollTop > 200) $goTop.addClass('show');
else $goTop.removeClass('show');
});
$goTop.on('click', function () {
gsap.to(window, { duration: 1, scrollTo: 0, ease: 'power2.out' });
});
Notable details
- Conic-gradient + radial mask creates a clean ring without an SVG — cheaper to repaint and easier to colour-theme via the
--primarycustom property. - The progress angle is written to a CSS custom property (
--progress) instead of touching inline style every frame — the browser handles interpolation. - Hides itself when within 200px of the top, also fades out near the footer (the JS additionally checks for footer overlap to avoid stacking with the back-to-top link).
Use when
- Long-scroll single-page sites where users benefit from a visual indicator of where they are.
- Brand themes that already have a primary CSS variable — the ring re-themes for free.
Caveats
- The radial-mask fallback for older Safari (pre 15.4) is missing — add
-webkit-mask(already present) and consider an SVG fallback for legacy browsers. - The
scrolllistener is not throttled; on long pages or low-power devices, swap to ScrollTrigger.update or rAF throttling.