
1. 탑버튼
탑버튼(Top Button, 상단 이동 버튼)은 세로로 긴 웹페이지에서 사용자가 스크롤을 내렸을 때 클릭 한 번으로 문서 최상단으로 되돌아갈 수 있도록 돕는 인터페이스 요소이다. 스크롤 위치에 따라 화면에 동적으로 표시되거나 사라지며, 클릭 시 부드러운 스크롤 애니메이션과 함께 시작 지점으로 이동하는 기능을 제공한다. 본 문서에서는 제이쿼리(jQuery) 라이브러리를 활용한 구현 방식과 순수 자바스크립트(Vanilla JavaScript, 바닐라 자바스크립트)를 활용한 구현 방식을 각각 설명한다.
1.1. 제이쿼리
지시문
사용자의 스크롤 동작을 감지하여 화면 우측 하단에 고정된 탑버튼이 나타나고, 버튼 클릭 시 부드러운 애니메이션과 함께 최상단으로 이동하도록 요구사항을 구성한다.
탑버튼을 만들어보자
HTML
스크롤이 발생하는 본문 영역과 상단 이동 링크 버튼의 기본 마크업 구조를 작성한다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
</head>
<body>
<div class="dummy">
<p>Lorem ipsum Enim do velit exercitation fugiat cillum labore et dolore ad minim dolor amet tempor nisi sunt Excepteur voluptate laborum et Duis labore cupidatat officia laboris minim cupidatat sit ad incididunt dolor in nulla elit sint do sit aliqua eu ut irure commodo exercitation dolore consequat est laborum Duis in dolore esse est dolore voluptate amet fugiat cupidatat Duis proident consequat nostrud Excepteur ea minim nisi eiusmod sed amet irure id ut officia occaecat nisi elit velit qui aliquip adipisicing consequat adipisicing aute laboris do consectetur sit officia elit in tempor aute eiusmod nulla dolore non sint in fugiat adipisicing amet quis in velit sit sunt Duis culpa deserunt Duis sed elit veniam exercitation Ut pariatur magna et id esse dolor dolore aliquip et in cillum commodo commodo et quis veniam magna irure laborum commodo enim tempor dolore velit ut adipisicing consequat dolore enim sunt eiusmod irure aliquip Duis magna laboris non in aliquip magna dolor dolore nulla nisi proident cupidatat laboris eu commodo adipisicing adipisicing ut aliquip eu aute veniam sint magna mollit nostrud ut sed consectetur et tempor consequat nisi nostrud dolore et officia adipisicing labore id enim nisi reprehenderit sunt fugiat ea Ut dolore sed eu in id velit esse et est labore eiusmod culpa adipisicing quis ea consectetur ea fugiat in culpa magna do laboris.</p>
<p>Lorem ipsum Proident irure magna dolore quis laboris deserunt ad aliquip non nostrud laborum sed et commodo ut elit cupidatat amet dolore est Ut aute et nulla dolore officia velit Ut ullamco id qui velit cupidatat dolore sed deserunt sed sed sit mollit labore esse laboris cupidatat Duis quis est ea mollit id nostrud Ut nostrud magna veniam cupidatat officia magna consectetur adipisicing sit exercitation est nisi ut fugiat exercitation non in dolor aute laborum anim incididunt commodo ut Duis cupidatat do in aliquip ea amet elit eiusmod ea nulla sed amet labore Duis incididunt do anim dolor culpa non aute cupidatat enim reprehenderit do eu esse commodo et dolor aliquip magna sint Excepteur deserunt dolore laboris magna occaecat non ea in proident voluptate nulla amet officia consequat Ut laboris irure non incididunt Ut eu id aliquip ea minim dolor nostrud ad labore incididunt ut in veniam sunt eiusmod est eiusmod anim sed ea pariatur id tempor commodo sint qui sit do Excepteur ut.</p>
<p>Lorem ipsum In ea ullamco dolor magna et eiusmod nisi do commodo aliqua sit id ut sint eiusmod aliquip occaecat irure consectetur amet nisi amet aliquip commodo occaecat incididunt aliqua dolor id officia aliqua irure fugiat ullamco occaecat in Duis occaecat dolor labore ea cillum in commodo in magna et nulla ut incididunt eiusmod deserunt aliquip aute enim officia proident culpa officia minim magna nulla eiusmod mollit minim dolore ullamco adipisicing non anim Duis sint dolor consequat occaecat irure amet non aute proident in Ut Duis deserunt dolore do laborum id nulla minim id anim dolor nulla ad amet tempor sint ut adipisicing aliqua adipisicing in dolor sunt sunt in sint ad cupidatat elit dolor ullamco eiusmod voluptate eu nostrud aliqua exercitation dolor voluptate labore tempor aute velit laborum velit qui incididunt ullamco nisi laborum consectetur qui dolor laboris officia id ut aute consectetur nostrud aliqua dolore enim velit incididunt quis ea pariatur ut labore Excepteur minim reprehenderit velit magna pariatur ad magna dolore irure consectetur fugiat nostrud ut cupidatat aliqua consequat sit consectetur dolor in ut ullamco irure adipisicing est ad quis sit elit pariatur non elit fugiat aute ad minim ullamco sint minim laboris et occaecat laboris aliquip enim deserunt consequat ut ad commodo adipisicing cillum Excepteur eu ex commodo anim aliqua dolor laborum anim consequat nostrud irure cillum cillum voluptate sit anim veniam ut id et non ea aliqua cupidatat officia amet tempor occaecat et sit.</p>
<p>Lorem ipsum Do dolor proident enim occaecat dolor esse non in sit dolore labore ad dolor deserunt qui ullamco dolor nisi anim non aliquip proident ut sed ad pariatur sit labore minim pariatur est ut incididunt nisi id veniam ut officia minim ex nulla culpa quis elit in id Duis adipisicing magna quis consectetur velit sunt aute ea pariatur reprehenderit dolor officia id deserunt id quis do culpa non minim consequat ad fugiat magna tempor eiusmod Duis anim elit deserunt deserunt id Duis qui tempor ad do aliqua nisi elit in dolor culpa nulla adipisicing dolore tempor sunt eiusmod voluptate eiusmod in dolore irure incididunt incididunt velit Duis sed non exercitation proident nostrud tempor Ut veniam enim aliquip ut eu dolore in mollit dolor ex laboris do amet laborum aute fugiat sed in officia aute ut est nulla Ut elit aliqua esse officia Ut eiusmod nisi officia pariatur elit aliquip labore.</p>
</div>
<a href="#top" class="go-top" title="Back to Top"><i class="fa fa-arrow-up"></i></a>
</body>
</html>
HTML 구조는 스크롤을 생성하기 위한 더미(Dummy, 임시 대체물) 텍스트 영역인 div.dummy와 상단 이동 기능을 수행할 a.go-top 링크 요소로 구성된다.
<head> 영역에서는 제이쿼리 코어 라이브러리와 함께 제이쿼리 UI(jQuery UI) 라이브러리를 불러온다. 제이쿼리 UI는 기본 애니메이션 함수에 다양한 감속 곡선(Easing, 이징) 효과를 추가하기 위해 사용된다. a.go-top 요소 내부에는 화살표 모양을 나타내기 위한 폰트 어썸(Font Awesome) 아이콘 태그(i.fa.fa-arrow-up)가 배치되어 있다.
실제 환경에서 폰트 어썸 스타일시트가 포함되어 있지 않으면 아이콘이 화면에 표시되지 않고 빈 영역으로 남을 수 있다. 또한 a 태그에 href="#top"이 지정되어 있으므로, 스크립트 애니메이션과 충돌하지 않도록 자바스크립트에서 기본 이벤트 동작을 취소해야 한다.
CSS
탑버튼의 화면 고정 위치와 크기, 초기 숨김 상태를 스타일시트로 정의한다.
body {
background-color: rgb(255, 255, 255);
color: rgb(0, 0, 0);
min-width: 960px;
}
.dummy {
margin: 0 auto;
max-width: 32em;
padding: 6em 0;
}
/* GOTOP BTN */
.go-top {
width: 48px;
height: 48px;
display: none;
position: fixed;
bottom: 48px;
right: 48px;
text-align: center;
color: #fff;
}
.go-top .fa {
width: 48px;
height: 48px;
background: #666;
display: inline-block;
line-height: 48px;
}
.go-top 클래스는 position: fixed 속성을 사용하여 브라우저 뷰포트(Viewport, 웹페이지가 화면에 표시되는 영역)를 기준으로 위치를 고정한다. 화면 우측 하단에 배치하기 위해 bottom: 48px와 right: 48px 값을 지정한다.
초기 상태에서는 페이지 최상단에 위치하므로 버튼이 보이지 않아야 한다. 이를 위해 display: none을 설정하여 화면 표시 대상에서 제외한다. 내부 아이콘인 .go-top .fa는 가로 48px, 세로 48px 크기에 line-height: 48px를 지정하여 아이콘이 상하좌우 중앙에 정렬되도록 구성한다.
position: absolute를 사용하면 스크롤 시 버튼이 문서를 따라 위로 밀려 올라가므로 반드시 fixed를 사용해야 한다. 또한 다른 콘텐츠 영역에 버튼이 가려지지 않도록 필요한 경우 z-index 속성을 추가하여 표시 순위를 제어해야 한다.
JQ
제이쿼리의 스크롤 이벤트와 애니메이션 메서드를 사용하여 버튼의 노출 전환 및 상단 이동 동작을 구현한다.
$(function () {
// Show/hide the footer button
$(window).scroll(function () {
if ($(this).scrollTop() > 300) {
$('.go-top').fadeIn(200);
} else {
$('.go-top').fadeOut(200);
}
});
// Animate scrolling
$('.go-top').click(function (e) {
e.preventDefault();
$('html, body').animate({ scrollTop: 0 }, 500, 'easeOutQuart');
});
});
$(window).scroll() 이벤트 리스너(Event Listener, 특정 사건의 발생을 감시하는 함수)를 통해 사용자가 화면을 스크롤할 때마다 수직 스크롤 위치를 감지한다. $(this).scrollTop() 값이 300px을 초과하면 fadeIn(200)을 실행하여 0.2초에 걸쳐 버튼을 서서히 나타나게 하고, 300px 이하일 때는 fadeOut(200)으로 서서히 사라지게 처리한다.
버튼 클릭 이벤트에서는 e.preventDefault()를 호출하여 <a> 태그의 기본 해시 이동 동작을 차단한다. 그 후 $('html, body').animate({ scrollTop: 0 }, 500, 'easeOutQuart')를 실행하여 0.5초 동안 최상단으로 부드럽게 스크롤되도록 처리한다. 여기서 easeOutQuart는 도착 지점에 가까워질수록 속도가 완만하게 줄어드는 감속 효과를 부여한다.
스크롤 대상 선택자로 html과 body를 함께 지정하는 이유는 브라우저 엔진에 따라 스크롤 기준 요소(웹킷 기반의 body와 파이어폭스 등의 html)가 다르기 때문이다. 또한 easeOutQuart와 같은 확장 이징 함수는 제이쿼리 코어만으로는 동작하지 않으며 제이쿼리 UI 라이브러리가 로드되어 있어야 정상 실행된다.
1.2. vanilla JS
외부 라이브러리 없이 웹 표준 API만을 사용하여 동일한 탑버튼 기능을 구현한다.
window.addEventListener('scroll', function () {
if (this.scrollY > 300) {
document.querySelector('.go-top').style.display = 'block';
} else {
document.querySelector('.go-top').style.display = 'none';
}
});
document.querySelector('.go-top').addEventListener('click', function (e) {
e.preventDefault();
document.querySelector('html, body').scrollTo({ top: 0, behavior: 'smooth' });
});
순수 자바스크립트 방식에서는 window.addEventListener('scroll', ...)를 통해 브라우저의 스크롤 이벤트를 감지한다. 현재 스크롤 위치는 this.scrollY 속성으로 확인하며, 300px을 기준으로 document.querySelector('.go-top').style.display 값을 'block' 또는 'none'으로 변경하여 버튼을 노출하거나 숨긴다.
버튼 클릭 시에는 e.preventDefault()로 기본 링크 동작을 막고, document.querySelector('html, body').scrollTo({ top: 0, behavior: 'smooth' })를 실행하여 상단으로 스크롤을 이동시킨다. behavior: 'smooth' 옵션은 브라우저 내장 스무스 스크롤 기능을 활성화하여 별도의 타이머 계산 없이 부드러운 전환을 수행한다.
제이쿼리의 페이드 애니메이션과 달리 style.display를 직접 변경하는 방식은 버튼이 즉시 나타나고 사라진다. 부드러운 전환 효과가 필요하다면 CSS의 opacity 속성과 transition(트랜지션, 속성 변화에 걸리는 시간을 제어하는 전환 효과) 속성을 결합하여 클래스 추가 및 제거 방식으로 제어해야 한다.