Tags
JavaScript
Created
April 8, 2024
먼저, 스크롤 이벤트에 관한 기본적인 내용들은 여기서 학습하면 된다.
박스 끝까지 스크롤 시 알림 띄우기
요즘 이용약관이나 긴 문서를 스크롤 다 내려 읽었을 때 버튼이 활성화되는 UX는 흔히 볼 수 있다. 사용자가 실제로 문서를 읽었다는 것을 확인하는 데 유용하다. 다 읽은 것을 확인할 수 있는 방법은 무엇인가?
바로, 사용자가 문서를 끝까지 스크롤했는지 감지하는 것이다.
나는 사용자가 스크롤한 위치가 이용약관 전체 높이와 같아질 때, 버튼을 활성화하면 된다고 생각했다. 그게 문서를 끝까지 읽은 것이니까. 하지만 이렇게 비교하니 오차가 있었다. 문제를 파악하기 전 아래 개념을 알고 있자.
scrollTop
: 사용자가 스크롤한 위치scrollHeight
: 스크롤 가능한 전체 높이(요소의 전체 높이를 나타내는 값)clientHeight
: 보이는 영역의 높이
Problem
초기 상태
스크롤하지 않은 상태.
scrollTop
= 0scrollHeight
= 900px (예: 전체 높이)clientHeight
= 300px (예: 보이는 높이)
+------------------------+
| |
| 보이는 영역 300px |
| |
+------------------------+ <- 여기가 보이는 영역의 끝 (clientHeight)
| | \
| | \
| | \
| 전체 콘텐츠 | > scrollHeight 900px
| | /
| | /
| | /
+------------------------+
스크롤한 상태
스크롤이 중간쯤 내려갔을 때.
scrollTop
= 300pxscrollHeight
= 900px (전체 높이)clientHeight
= 300px (보이는 높이)
+------------------------+
| | \
| | \
| | \
+------------------------+ > scrollTop 300px
| |
| 보이는 영역 300px |
| |
+------------------------+
| |
| |
+------------------------+
스크롤을 끝까지 내린 상태
스크롤이 맨 아래로 내려갔을 때
scrollTop
= 600pxscrollHeight
= 900px (전체 높이)clientHeight
= 300px (보이는 높이)
+------------------------+
| |
| |
| | <- 여기가 스크롤의 끝
+------------------------+
| 보이는 영역 300px |
| |
+------------------------+
이 상태에서, scrollTop
값은 600px이다. 단순히 scrollTop
과 scrollHeight
를 비교하면, scrollTop
(600px)과 scrollHeight
(900px)으로 300px 차이가 나므로 스크롤이 끝까지 되지 않았다고 판단할 수 있다. 하지만, 실제로 사용자는 이미 끝까지 스크롤한 상태다.
왜 그럴까? 바로 scrollTop
의 특성 때문이다. 즉, 스크롤바 내린 양은 진짜 스크롤바만 내린 양이고, 보이는 영역의 높이는 포함하지 않아서 그렇다.
Conclusion
scrollTop
과 scrollHeight
를 비교할 때는 clientHeight
값을 고려해야 한다. 정확한 비교는 scrollTop + clientHeight
와 scrollHeight
을 비교하는 것.
scrollTop
+clientHeight
= 600px + 300px = 900pxscrollHeight
= 900px
<body>
<div id="terms">
<p>
<!-- 여기에 이용약관 내용이 들어갑니다 -->
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit
in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<!-- 더 많은 내용 -->
...
</div>
<button id="agreeButton" disabled>Agree</button>
<script>
const terms = document.getElementById('terms');
const agreeButton = document.getElementById('agreeButton');
terms.addEventListener('scroll', function() {
// 스크롤 가능한 전체 높이에서 가시 높이를 뺀 값을 사용하여 비교
if (terms.scrollTop + terms.clientHeight >= terms.scrollHeight) {
agreeButton.disabled = false;
agreeButton.classList.add('enabled');
} else {
agreeButton.disabled = true;
agreeButton.classList.remove('enabled');
}
});
</script>
</body>