: 스크롤(scroll) 시 발생하는 이벤트
window.addEventListener('scroll', function() {
속성
});
window
: html 페이지window.scrollY
: 전체 페이지에서 스크롤바를 얼만큼 내렸는지 숫자로 출력
window.scrollX
: 가로 스크롤
window.scrollTo(x, y)
: 원하는 좌표로 강제로 스크롤 변경
window.scrollBy(x, y)
: 현재 위치에서부터 강제로 스크롤하기
window.addEventListener('scroll', function() {
window.scrollTo(0, 100);
});
jquery 버전
scrollTop()
$(window).on('scroll', function() {
$(window).scrollTop(100)
// 현재 위치에서 y축으로 100만큼 이동
})
<div>
상자에서의 스크롤.scrollTop
: 특정 <div>
상자에서 스크롤바를 내린 양.clientHeight
: 현재 화면에 보이는 <div>
상자의 높이
.scrollHeight
: 특정 <div>
상자의 전체 높이
document.querySelector('.lorem').addEventListener('scroll', function() {
var 스크롤양 = document.querySelector('.lorem').scrollTop; // 188
var 높이 = document.querySelector('.lorem').clientHeight; // 100
var 실제높이 = document.querySelector('.lorem').scrollHeight; // 288
<html>
의 스크롤document.querySelector('html').scrollHeight
: html(전체 페이지)의 높이
(= document.documentElement.scrollHeight
)
document.querySelector('html').clientHeight;
: 현재 화면에 보이는 부분의 높이
window.screenY
: 현재 페이지의 스크롤 높이
overflow-x: scroll;
: 세로 스크롤 만들기
overflow-y: scroll;
: 가로 스크롤 만들기
position: fixed;
: 상단 고정 (스크롤 되어도 상단에 고정됨)
:root {
scroll-behavior: auto;
}
scroll 이벤트 리스너 안의 코드는 1초에 60번 이상 실행됨
scrollHeight 구할 땐 브라우저마다 아주 약간의 오차가있을 수 있어서 테스트 해보는게 좋다.
scrollHeight 구하는 코드는 페이지 로드가 완료되고나서 실행해야 정확하기 때문에 <body>
끝나기 전에 적는게 좋다.
.removeEventListener('scroll', arguments.callee);
.removeEventListener()
: 추가한 이벤트를 제거하는 함수
- 필요한 요소:
1. 제거할 엘리먼트(element) 요소
2. 이벤트 타입 (click, scroll, keypress 등)
3. 제거할 이벤트의 callback 함수
arguments.callee
: 현재 실행 중인 함수를 참조할 수 있는 속성
- callback 함수가 없는 경우(= 익명 함수) 이벤트를 제거 할 수 있다. 이때 이벤트 함수의 콜백 함수는 반드시 function 키워드로 작성해야 한다.
let hasScrolled = false;
true
로 변경<div>
상자의 높이보다 작으면 다시 false
로 변경window.addEventListener('scroll', function() {
// 스크롤바가 움직일 때마다 실행되어야 하기 때문에 이벤트리스너 사용
if (window.scrollY > 100) {
document.getElementsByClassName('navbar-brand')[0].style.fontSize = '20px'
} else if (window.scrollY < 100) {
document.getElementsByClassName('navbar-brand')[0].style.fontSize = '25px'
}
});
1. <div>
상자 바닥 체크하기
if (div 상자에서 스크롤바 내린 높이 + 현재 화면에 보이는 div 상자의 높이 > div 상자의 실제 높이 - 10) {
// .scrollTop + .clientHeight > .scrollHeight - 10
alert()
}
2. 소수점 때문에 오차가 발생할 수 있기 때문에
끝까지 스크롤한 것보다는 끝에서 10px 정도 남기고 스크롤 했는지 검사하기
3. 위로 올렸다가 다시 스크롤하면 alert창 계속 띄우기
let hasScrolled = false;
const lorem = document.querySelector('.lorem');
let hasScrolled = false;
lorem.addEventListener('scroll', function() {
let scrollLength = lorem.scrollTop; // 스크롤 끝까지 내린 위치
let loremCHeight = lorem.clientHeight; // 보여지는 div 높이
let loremSHeight = lorem.scrollHeight; // 콘텐츠 전체 높이
if ((scrollLength + loremCHeight) >= (loremSHeight - 10) && !hasScrolled) {
alert('약관을 확인했습니다.');
hasScrolled = true;
}
// 위로 올렸다가 다시 스크롤하면 alert창 계속 띄우기
if (scrollLength < loremCHeight) { // 스크롤 위치(scrollLength)가 보여지는 약관 div 높이(loremCHeight)보다 작으면
hasScrolled = false;
}
});
}
1. <div>
상자 바닥 체크하기
2. 위로 올렸다가 다시 스크롤하면 alert창 계속 띄우기
let hasScrolled = false;
window.addEventListener('scroll', function() {
var loremSHeight = document.querySelector('html').scrollHeight; // html(전체 페이지)의 높이
var loremCHeight = document.querySelector('html').clientHeight; // 현재 화면에 보이는 부분의 높이
var scrollLength = document.querySelector('html').scrollTop; // 현재 페이지의 스크롤양
if ((scrollLength + loremCHeight) > (loremSHeight - 5) && !hasScrolled) {
alert('페이지를 모두 확인했습니다.')
hasScrolled = true;
}
// 위로 올렸다가 다시 스크롤하면 alert창 계속 띄우기
if (scrollLength < loremCHeight) { // 스크롤 위치(scrollLength)가 보여지는 약관 div 높이(loremCHeight)보다 작으면
hasScrolled = false;
}
});
const progress = ((scrollLength + loremCHeight) / loremSHeight) * 100;
document.querySelector('.ui').style.width = progress + '%';
const progress = ((scrollLength + loremCHeight) / loremSHeight) * 100;
if (progress < 16) {
this.document.querySelector('.ui').style.width = '0%';
} else if (progress < 20) {
this.document.querySelector('.ui').style.width = '20%';
} else if (progress < 40) {
this.document.querySelector('.ui').style.width = '40%';
} else if (progress < 60) {
this.document.querySelector('.ui').style.width = '60%';
} else if (progress < 80) {
this.document.querySelector('.ui').style.width = '80%';
} else if (progress < 95) {
this.document.querySelector('.ui').style.width = '95%';
} else if (progress > 97) {
this.document.querySelector('.ui').style.width = '100%';
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Bootstrap CSS -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous"
/>
<link href="main.css" rel="stylesheet" />
<title>Hello, world!</title>
</head>
<body>
<!-- 진행바 -->
<div class="ui"></div>
<nav class="navbar navbar-light bg-light">
<div class="container-fluid">
<span class="navbar-brand">Question</span>
<button class="navbar-toggler" type="button">
<!--Navbar 버튼-->
<span class="navbar-toggler-icon"></span>
</button>
</div>
</nav>
<!-- 걍 스크롤이 필요해서 만든 큰 박스임 -->
<div style="height: 2000px"></div>
<div class="lorem" style="width: 200px; height: 100px; overflow-y: scroll;">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae voluptas voluptatum minus praesentium fugit debitis at, laborum ipsa itaque placeat sit, excepturi eius. Nostrum perspiciatis, eligendi quae consectetur praesentium exercitationem.
</div>
<script src="index.js"></script>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"
></script>
</body>
</html>
index.js
// 1. 스크롤바 내리면 로고 폰트 작게 만들기
// - 스크롤바 100px 이상 내리면 로고 폰트 사이즈 줄이기
window.addEventListener('scroll', function() {
if (window.scrollY > 100) {
document.getElementsByClassName('navbar-brand')[0].style.fontSize = '20px'
} else if (window.scrollY < 100) {
document.getElementsByClassName('navbar-brand')[0].style.fontSize = '25px'
}
// 3. 현재 페이지의 끝까지 스크롤 체크하기
// + alert창 계속 띄우기
var loremSHeight = document.querySelector('html').scrollHeight; // html(전체 페이지)의 높이
var loremCHeight = document.querySelector('html').clientHeight; // 현재 화면에 보이는 부분의 높이
var scrollLength = document.querySelector('html').scrollTop; // 현재 페이지의 스크롤양
if ((scrollLength + loremCHeight) > (loremSHeight - 5) && !hasScrolled) {
alert('페이지를 모두 확인했습니다.')
hasScrolled = true;
}
// 위로 올렸다가 다시 스크롤하면 alert창 계속 띄우기
if (scrollLength < loremCHeight) { // 스크롤 위치(scrollLength)가 보여지는 약관 div 높이(loremCHeight)보다 작으면
hasScrolled = false;
}
// 4. 상단의 진행바 만들기
// 전체 세로폭 중 현재까지 스크롤한 값을 백분률 환산
// (브라우저 최하단까지 스크롤을 내리면 100%가 됨)
// 방법 1. 백분률에 %를 붙여서 바로 진행바 길이 조정하기
const progress = ((scrollLength + loremCHeight) / loremSHeight) * 100;
document.querySelector('.ui').style.width = progress + '%';
// 방법 2. 백분률을 직접 나눠서 길이 부여하기
if (progress < 16) {
this.document.querySelector('.ui').style.width = '0%';
} else if (progress < 20) {
this.document.querySelector('.ui').style.width = '20%';
} else if (progress < 40) {
this.document.querySelector('.ui').style.width = '40%';
} else if (progress < 60) {
this.document.querySelector('.ui').style.width = '60%';
} else if (progress < 80) {
this.document.querySelector('.ui').style.width = '80%';
} else if (progress < 95) {
this.document.querySelector('.ui').style.width = '95%';
} else if (progress > 97) {
this.document.querySelector('.ui').style.width = '100%';
}
});
// 2. 회원 약관 끝까지 읽으면 alert 띄우기
// + alert창 계속 띄우기
const lorem = document.querySelector('.lorem');
let hasScrolled = false;
lorem.addEventListener('scroll', function() {
let scrollLength = lorem.scrollTop; // 스크롤 끝까지 내린 위치
let loremCHeight = lorem.clientHeight; // 보여지는 div 높이
let loremSHeight = lorem.scrollHeight; // 콘텐츠 전체 높이
if ((scrollLength + loremCHeight) >= (loremSHeight - 10) && !hasScrolled) {
alert('약관을 확인했습니다.');
hasScrolled = true;
}
// 위로 올렸다가 다시 스크롤하면 alert창 계속 띄우기
if (scrollLength < loremCHeight) { // 스크롤 위치(scrollLength)가 보여지는 약관 div 높이(loremCHeight)보다 작으면
hasScrolled = false;
}
});
main.css
.navbar {
position: fixed;
/* 상단 고정(스크롤 되어도 상단에 고정됨) */
width: 100%;
z-index: 5;
}
/* 스크롤바 내리면 로고 작게 만들기 */
.navbar-brand {
font-size: 25px;
/* 시작 스타일: 애니메이션 작동 전의 글씨 크기 */
transition: all 2s;
}
.small {
font-size: 20px;
}
.show {
display: block;
}
.ui {
background-color: red;
padding: 1px;
width: 0%;
position: fixed;
z-index: 10;
transition: all 1s;
}
https://developer.mozilla.org/ko/docs/Web/API/Element/scrollHeight
출처
코딩애플
https://ko.javascript.info/size-and-scroll-window
https://developer.mozilla.org/ko/docs/Web/API/Element/scrollHeight
https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%A0%9C%EA%B1%B0-%ED%95%9C%EB%B2%88%EB%A7%8C-%EC%8B%A4%ED%96%89%EB%90%98%EA%B2%8C-%ED%95%98%EA%B8%B0-removeEventListener-once
https://kincoding.com/entry/%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EC%A7%84%ED%96%89%EB%A5%A0%EC%9D%84-%ED%91%9C%EC%8B%9C%ED%95%B4%EB%B3%B4%EC%9E%90-%EC%83%81%EB%8B%A8-progress-bar-%EB%A7%8C%EB%93%A4%EA%B8%B0