코드공부방

스크롤 감지하여 고정메뉴 노출/비노출 처리 이벤트 본문

웹퍼블리셔/JavaScript

스크롤 감지하여 고정메뉴 노출/비노출 처리 이벤트

:- ) 2019. 9. 4. 15:15
반응형

스크롤 감지하여 고정메뉴 노출/비노출 처리 이벤트


상단, 하단에 모두 고정 메뉴나 콘텐츠가 있는 경우 모바일 환경에서는 콘텐츠를 볼 수 있는 영역이 좁아 부담스러울 수 있다. 따라서 사용자가 스크롤을 올리는지, 내리는지 체크하여 하단고정메뉴를 노출 또는 비노출 처리하여 콘텐츠를 볼 수 있는 영역을 유동적으로 넓힐 수 있다.

 

<!-- 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;}

bottom에 고정된 콘텐츠

바닥에 고정되어있는 네비게이션을 숨김/보임 처리 하려면 사용자가 스크롤을 올렸는지, 내렸는지 감지가 되야 한다. 사용자의 스크롤을 감지하는 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;
}

사용자의 스크롤을 감지하여 bottom고정된 영역을 숨김/보임 처리한다.

본 예제는 하단에 고정된 영역을 숨김/보임 처리하는 결과물이지만 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 구현하기

 

무한스크롤 (Infinity Scroll) UI 구현하기

무한스크롤 (Infinity Scroll) UI 구현하기 쇼핑몰이나 상품 또는 게시글 목록에서 갯수가 많아지면 자연스럽게 페이징(Page nate, pagenation 등으로도 불리운다) 처리를 하게 된다. 근데 PC에서 쓰이는 페이징..

code-study.tistory.com

2019/09/03 - [UI 클론(Clone)] - 구글 로그인 인풋박스(Google Login Inputbox) UI Clone

 

구글 로그인 인풋박스(Google Login Inputbox) UI Clone

구글 로그인 인풋박스(Google Login Inputbox) UI Clone 오래전부터 구글의 로그인폼을 보면 쌈박하다는 생각이 들었다. 요즘은 꽤 대중화된(?) 방식이지만 자칫 딱딱해보일 수 있는 form label에 저런 인터랙션을..

code-study.tistory.com

2019/08/28 - [JavaScript] - 강제로 body 스크롤막기 (PC, Mobile (iOS, Android..) 모든 환경)

 

강제로 body 스크롤막기 (PC, Mobile (iOS, Android..) 모든 환경)

레이어팝업을 띄우면 뒤쪽 콘텐츠의 스크롤을 막아달라는 요청이 간혹 있다. (그냥 스크롤이 가능하게 되길 희망하는 클라이언트도 있다.) /* CSS */ .hidden {height:100%; min-height:100%; overflow:hidden !i..

code-study.tistory.com

2019/08/28 - [CSS] - CSS 반응형 작업 시 박스 비율 유지하기

 

CSS 반응형 작업 시 박스 비율 유지하기

작업을 하다보면 리사이즈 됨에도 박스비율을 유지해야 하는 경우가 있다. (특히 반응형 작업에서) 박스의 width값은 100%로 지정하면 되지만 height값을 어떻게 해야 박스의 비율을 유지할 수 있을까? max-width..

code-study.tistory.com

 

반응형
Comments