원형 프로그레스 바(Circular Progress Bar)가 포함된 Scroll-to-Top 버튼
사용자가 페이지를 스크롤할 때 스크롤 진행률을 0~100% 수치와 원형 테두리(Circular Progress Bar)로 시각화해주는 'Top으로 이동' 버튼을 만들어줘. 클릭하면 페이지 최상단으로 부드럽게 이동해야 하고, 스크롤을 어느 정도 내렸을 때만 나타나게 해줘. 아래 코드를 참고 하면 됩니다.
=====================================
Scroll to Top 버튼 (원형 진행률)
=====================================
[1] HTML
-------------------------------------
</body> 바로 위에 배치.
Lucide Icons CDN 미사용 시 <i data-lucide> 대신
인라인 SVG로 교체 (아래 대체 코드 참고).
<div id="scrollTopBtn" role="button" tabindex="0" aria-label="Back to top">
<div class="scroll-top-bg"></div>
<svg class="scroll-progress-ring" viewBox="0 0 44 44" aria-hidden="true">
<circle class="scroll-progress-track" cx="22" cy="22" r="18"/>
<circle class="scroll-progress-fill" cx="22" cy="22" r="18" id="scrollProgressFill"/>
</svg>
<div class="scroll-top-inner">
<i data-lucide="chevron-up" class="scroll-top-arrow"></i>
<span class="scroll-top-pct" id="scrollTopPct">0%</span>
</div>
</div>
* Lucide 없이 쓸 때 아이콘 대체:
<svg class="scroll-top-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>
[2] CSS
-------------------------------------
색상 3곳을 프로젝트에 맞게 변경.
#scrollTopBtn {
position: fixed;
bottom: 28px;
right: 24px;
width: 50px;
height: 50px;
cursor: pointer;
opacity: 0;
visibility: hidden;
transform: translateY(12px);
transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
z-index: 990;
display: flex;
align-items: center;
justify-content: center;
-webkit-tap-highlight-color: transparent;
}
#scrollTopBtn.visible {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
#scrollTopBtn:hover {
transform: translateY(-3px);
}
.scroll-top-bg {
position: absolute;
inset: 0;
border-radius: 50%;
background: #1a1a2e; /* [색상1] 기본 배경 */
box-shadow: 0 4px 16px rgba(26, 26, 46, 0.28);
transition: background-color 0.2s ease, box-shadow 0.2s ease;
}
#scrollTopBtn:hover .scroll-top-bg {
background: #16213e; /* [색상2] hover 배경 */
box-shadow: 0 6px 22px rgba(26, 26, 46, 0.4);
}
.scroll-progress-ring {
position: absolute;
width: 100%;
height: 100%;
transform: rotate(-90deg);
}
.scroll-progress-track {
fill: none;
stroke: rgba(255, 255, 255, 0.18);
stroke-width: 3;
}
.scroll-progress-fill {
fill: none;
stroke: #e94560; /* [색상3] 진행률 링 */
stroke-width: 3;
stroke-linecap: round;
stroke-dasharray: 113.1;
stroke-dashoffset: 113.1;
transition: stroke-dashoffset 0.12s linear;
}
.scroll-top-inner {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 1px;
pointer-events: none;
user-select: none;
}
.scroll-top-arrow {
width: 14px;
height: 14px;
color: rgba(255, 255, 255, 0.95);
stroke-width: 2.8;
display: block;
}
#scrollTopBtn:hover .scroll-top-arrow {
animation: arrowBounce 0.45s ease forwards;
}
@keyframes arrowBounce {
0% { transform: translateY(0); }
35% { transform: translateY(-4px); }
65% { transform: translateY(-1px); }
100% { transform: translateY(-2px); }
}
.scroll-top-pct {
font-size: 9px;
font-weight: 700;
color: rgba(255, 255, 255, 0.82);
line-height: 1;
letter-spacing: -0.3px;
}
[3] JavaScript
-------------------------------------
</body> 직전 또는 DOMContentLoaded 안에서 실행.
외부 라이브러리 의존 없음.
(function () {
var scrollTopBtn = document.getElementById('scrollTopBtn');
var scrollTopPct = document.getElementById('scrollTopPct');
var progressFill = document.getElementById('scrollProgressFill');
var circumference = 2 * Math.PI * 18;
if (!scrollTopBtn || !progressFill) return;
function updateScrollTop() {
var scrolled = window.scrollY;
var docHeight = document.documentElement.scrollHeight - window.innerHeight;
var pct = docHeight > 0 ? Math.min(100, Math.round(scrolled / docHeight * 100)) : 0;
var offset = circumference * (1 - pct / 100);
progressFill.style.strokeDashoffset = offset;
if (scrollTopPct) scrollTopPct.textContent = pct + '%';
if (scrolled > 200) {
scrollTopBtn.classList.add('visible');
} else {
scrollTopBtn.classList.remove('visible');
}
}
window.addEventListener('scroll', updateScrollTop, { passive: true });
updateScrollTop();
scrollTopBtn.addEventListener('click', function () {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
scrollTopBtn.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
window.scrollTo({ top: 0, behavior: 'smooth' });
}
});
})();
[적용 체크리스트]
-------------------------------------
- 색상 3곳 변경 : [색상1] 기본배경, [색상2] hover배경, [색상3] 진행률링
- 아이콘 : Lucide CDN 없으면 인라인 SVG로 교체
- HTML 위치 : </body> 바로 위
- JS 로드 : </body> 직전 또는 DOMContentLoaded
- 외부 의존성 : 없음 (Vanilla JS + 순수 CSS)
scroll to top 버튼에 효과를 줄 때 사용하는 프롬프트
언어: Plain Text