일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 프레임워크
- CSS애니메이션
- 자기개발
- css규칙
- 웹스크래핑
- 투두리스트
- javascript
- 개발회고
- 자바스크립트
- vue-cli
- CSS로딩
- vueJS
- 코딩가이드
- 뉴스수집
- Vue.js
- 로딩UI
- 구글CSS
- html제거
- @keyframes
- google style guide
- to do list
- 코딩규칙
- vuejs입문
- 구글스타일가이드
- css rule
- 파이썬
- 코딩컨밴션
- 스타일가이드
- MariaDB
- python
- Today
- Total
코드공부방
스크롤 감지하여 고정메뉴 노출/비노출 처리 이벤트 본문
스크롤 감지하여 고정메뉴 노출/비노출 처리 이벤트
상단, 하단에 모두 고정 메뉴나 콘텐츠가 있는 경우 모바일 환경에서는 콘텐츠를 볼 수 있는 영역이 좁아 부담스러울 수 있다. 따라서 사용자가 스크롤을 올리는지, 내리는지 체크하여 하단고정메뉴를 노출 또는 비노출 처리하여 콘텐츠를 볼 수 있는 영역을 유동적으로 넓힐 수 있다.
<!-- HTML -->
<header>
<h1 class="pageTitle">Scroll check</h1>
</header>
<article>
<div class="block">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatem mollitia accusamus sequi ipsa, rerum nam laboriosam, ipsam aperiam deleniti beatae expedita id quisquam veritatis corporis, voluptates ducimus molestiae eum adipisci.
</p>
</div>
<div class="block">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatem mollitia accusamus sequi ipsa, rerum nam laboriosam, ipsam aperiam deleniti beatae expedita id quisquam veritatis corporis, voluptates ducimus molestiae eum adipisci.
</p>
</div>
<div class="block">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatem mollitia accusamus sequi ipsa, rerum nam laboriosam, ipsam aperiam deleniti beatae expedita id quisquam veritatis corporis, voluptates ducimus molestiae eum adipisci.
</p>
</div>
</article>
<nav class="bottomNav">
바닥 고정 네비게이션
</nav>
/* CSS */
.pageTitle,
.bottomNav {position: fixed; left: 0; bottom: 0; width: 100%; height: 52px; line-height: 52px; color: #fff; text-align: center;}
.pageTitle {top: 0; background:#111;}
.bottomNav {bottom: 0; background:#111;}
article {padding: 52px 3%;}
article .block {padding: 20px; min-height: 500px;}
article .block p {line-height: 22px; color: #fff; font-size: 16px; font-weight: 600;}
article .block:nth-child(2n+1) {background: #999;}
article .block:nth-child(2n) {background: #222;}
바닥에 고정되어있는 네비게이션을 숨김/보임 처리 하려면 사용자가 스크롤을 올렸는지, 내렸는지 감지가 되야 한다. 사용자의 스크롤을 감지하는 Javascript 코드는 아래와 같다.
//Javascript
var lastScrollTop = 0;
var delta = 5;
var fixBox = document.querySelector('.bottomNav');
var fixBoxHeight = fixBox.offsetHeight;
var didScroll;
//스크롤 이벤트
window.onscroll = function(e) {
didScroll = true;
};
//0.25초마다 스크롤 여부 체크하여 스크롤 중이면 hasScrolled() 호출
setInterval(function(){
if(didScroll){
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled(){
var nowScrollTop = window.scrollY;
if(Math.abs(lastScrollTop - nowScrollTop) <= delta){
return;
}
if(nowScrollTop > lastScrollTop && nowScrollTop > fixBoxHeight){
//Scroll down
console.log('scroll down');
}else{
if(nowScrollTop + window.innerHeight < document.body.offsetHeight){
//Scroll up
console.log('scroll up');
}
}
lastScrollTop = nowScrollTop;
}
이제 사용자가 스크롤을 올리는지, 내리는지 감지할 수 있게 되었다. 작동 원리는 매 0.25초마다 didScroll값을 체크하여 true일 경우 hasScrolled 함수를 호출한다. hasScrolled 함수에서는 현재 스크롤값이 delta값(5) 보다 큰지 우선 체크하고 작으면 즉시 함수를 종료(return)하고 delta값보다 크면 계산 로직을 실행한다. 현재 스크롤값이 마지막 스크롤값보다 크면 사용자가 스크롤을 내렸다고 판단하며 현재 스크롤값이 마지막 스크롤값보다 작으면서 동시에 현재 스크롤값과 윈도우(device)의 높이를 더한값이 문서(콘텐츠)의 총 높이값보다 작으면 사용자가 스크롤을 내렸다고 판단할 수 있다.
텍스트로 풀어 쓰니 복잡하고 어려워보이는데 코드로 보면 좀 더 이해가 빠르다. 스크롤을 올렸는지 내렸는지 감지할 수 있게 되었으니 남은 작업은 스크롤을 내리면 고정 네비게이션을 숨김처리하고 올리면 보임처리만 해주면 된다.
숨김, 보임처리는 Javascript에서 직접 처리하진 않고 Javascript에서는 스크롤 상/하 여부에 따라 .bottomNav 에 show 클래스를 토글시켜 CSS에서 숨김, 보임처리를 하면 된다. .bottomNav의 style을 아래와 같이 수정한다.
/* CSS */
.bottomNav {bottom: -52px; background:#111; transition:bottom .2s;}
.bottomNav.show {bottom: 0; background:#111;}
사용자가 스크롤을 내릴땐 show클래스를 삭제하고 올릴땐 show클래스를 추가하기 위하여 hasScrolled 함수를 수정한다.
//Javascript
function hasScrolled(){
var nowScrollTop = window.scrollY;
if(Math.abs(lastScrollTop - nowScrollTop) <= delta){
return;
}
if(nowScrollTop > lastScrollTop && nowScrollTop > fixBoxHeight){
//Scroll down (하단 고정메뉴 숨김)
fixBox.classList.remove('show');
}else{
if(nowScrollTop + window.innerHeight < document.body.offsetHeight){
//Scroll up (하단 고정메뉴 보임)
fixBox.classList.add('show');
}
}
lastScrollTop = nowScrollTop;
}
본 예제는 하단에 고정된 영역을 숨김/보임 처리하는 결과물이지만 hasScrolled 함수를 잘 응용하면 사용자의 스크롤에 따라 반응하는 여러가지 UI를 만들어낼 수 있다.
최종 HTML, CSS, Javascript 코드는 아래와 같다.
<!-- HTML -->
<header>
<h1 class="pageTitle">Scroll check</h1>
</header>
<article>
<div class="block">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatem mollitia accusamus sequi ipsa, rerum nam laboriosam, ipsam aperiam deleniti beatae expedita id quisquam veritatis corporis, voluptates ducimus molestiae eum adipisci.
</p>
</div>
<div class="block">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatem mollitia accusamus sequi ipsa, rerum nam laboriosam, ipsam aperiam deleniti beatae expedita id quisquam veritatis corporis, voluptates ducimus molestiae eum adipisci.
</p>
</div>
<div class="block">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatem mollitia accusamus sequi ipsa, rerum nam laboriosam, ipsam aperiam deleniti beatae expedita id quisquam veritatis corporis, voluptates ducimus molestiae eum adipisci.
</p>
</div>
</article>
<nav class="bottomNav">
바닥 고정 네비게이션
</nav>
/* CSS */
.pageTitle,
.bottomNav {position: fixed; left: 0; bottom: 0; width: 100%; height: 52px; line-height: 52px; color: #fff; text-align: center;}
.pageTitle {top: 0; background:#111;}
.bottomNav {bottom: -52px; background:#111; transition:bottom .2s;}
.bottomNav.show {bottom: 0; background:#111;}
article {padding: 52px 3% 0;}
article .block {padding: 20px; min-height: 500px;}
article .block p {line-height: 22px; color: #fff; font-size: 16px; font-weight: 600;}
article .block:nth-child(2n+1) {background: #999;}
article .block:nth-child(2n) {background: #222;}
//Javascript
var lastScrollTop = 0;
var delta = 5;
var fixBox = document.querySelector('.bottomNav');
var fixBoxHeight = fixBox.offsetHeight;
var didScroll;
//스크롤 이벤트
window.onscroll = function(e) {
didScroll = true;
};
//0.25초마다 스크롤 여부 체크하여 스크롤 중이면 hasScrolled() 호출
setInterval(function(){
if(didScroll){
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled(){
var nowScrollTop = window.scrollY;
if(Math.abs(lastScrollTop - nowScrollTop) <= delta){
return;
}
if(nowScrollTop > lastScrollTop && nowScrollTop > fixBoxHeight){
//Scroll down
fixBox.classList.remove('show');
}else{
if(nowScrollTop + window.innerHeight < document.body.offsetHeight){
//Scroll up
fixBox.classList.add('show');
}
}
lastScrollTop = nowScrollTop;
}
2019/09/04 - [JavaScript] - 무한스크롤 (Infinity Scroll) UI 구현하기
2019/09/03 - [UI 클론(Clone)] - 구글 로그인 인풋박스(Google Login Inputbox) UI Clone
2019/08/28 - [JavaScript] - 강제로 body 스크롤막기 (PC, Mobile (iOS, Android..) 모든 환경)
2019/08/28 - [CSS] - CSS 반응형 작업 시 박스 비율 유지하기
'웹퍼블리셔 > JavaScript' 카테고리의 다른 글
jQuery(제이쿼리) 동적으로 생성된 요소 이벤트 및 index(인덱스) 가져오기 (0) | 2020.02.10 |
---|---|
제이쿼리 쿠키(jQuery Cookie) 활용하여 오늘 하루 보지 않기 기능 구현하기 (12) | 2020.02.04 |
lozyload, 미디어 콘텐츠 지연로딩 시키기 (feat. jQuery Lazy) (0) | 2019.09.19 |
무한스크롤 (Infinity Scroll) UI 구현하기 (3) | 2019.09.04 |
강제로 body 스크롤막기 (PC, Mobile (iOS, Android..) 모든 환경) (2) | 2019.08.28 |