본문 바로가기
JavaScript

스크롤 이벤트로 와이즐리 헤더 만들기

by Vintz 2021. 8. 22.
반응형

와이즐리 헤더 기능 구현

탐나는 와이즐리 홈페이지의 헤더 이벤트

한때 와이즐리 사용자로서 이벤트를 하길래 오랜만에 들어와봤다. 옛날과 달리 홈페이지가 엄청 깔끔하고 보기에 편해진 것 같다. 그 중 와이즐리의 헤더 UI가 너무너무 신기했다. 

 

'이 UI 탐난다. 따라해봐야지'

 

생각하고 바로 실행에 옮겨봤다. 먼저 와이즐리의 헤더에 발생하는 이벤트를 정리해보자.

  1. 스크롤을 내리면 헤더의 배경 색상이 바뀐다. (transparent -> #fff)
  2. 조금 더 내리면 헤더가 올라간다. (translateY 사용)
  3. 스크롤을 올리면 헤더가 내려온다. (translateY 사용)
  4. 스크롤이 맨 위에 도착하면, 헤더의 배경 색상이 바뀐다. (#fff -> transparent)

HTML, CSS

헤더의 기능 구현에 목적을 두어서 페이지는 간단하게 만들었다. 헤더는 와이즐리와 구성이 비슷하게 만들어 봤다.

HTML

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>개발 전용차선</title>
    <link rel="stylesheet" href="style.css" />
    <script src="main.js" defer></script>
  </head>
  <body>
    <header>
      <div class="header-container">
        <a class="home" href="#">Only Dev</a>
        <nav class="menu">
          <a href="#">구독하기</a>
          <a href="#">상품보기</a>
          <a href="#">와이즐리 이야기</a>
          <a href="#">고객센터</a>
        </nav>
        <nav class="user-info">
          <a href="#">로그인</a>
          <a href="#">메뉴</a>
          <a href="#">장바구니</a>
        </nav>
      </div>
    </header>
    <section class="section1">
      <img class="avatar" src="avatarmaker.png" alt="아바타" />
    </section>
    <section class="section2">
      <h1>section 2</h1>
    </section>
    <section class="section3">
      <h1>section 3</h1>
    </section>
    <section class="section4">
      <h1>section 4</h1>
    </section>
    <section class="section5">
      <h1>section 5</h1>
    </section>
  </body>
</html>

CSS

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  background-color: #dfdbdb;
}

a {
  text-decoration: none;
  color: #111;
}

header {
  position: fixed;
  top: 0px;
  left: 0px;
  right: 0px;
  transition: transform 400ms ease-in-out 0s,
    background-color 400ms ease-in-out 0s;
  background-color: transparent;
}

.header-container {
  height: 68px;
  padding: 10px 40px;

  display: flex;
  justify-content: space-between;
  align-items: center;
}

.home {
  font-size: 21px;
  color: blue;
}

.menu {
  display: flex;
  flex-grow: 1;
  padding-left: 80px;
}

.menu a {
  font-size: 14px;
  line-height: 22px;
  color: #838383;
  letter-spacing: -0.04em;
}

.menu a:not(:first-child) {
  padding-left: 18px;
}

.user-info {
  font-size: 14px;
}

.user-info a:not(:last-child) {
  padding-right: 26px;
}

section {
  display: flex;
  justify-content: center;
  align-items: center;

  font-size: 24px;
  height: 800px;
}

.avatar {
  width: 500px;
  height: 500px;
}

기능 구현

기능 구현을 하는데 시행착오를 좀 겪었다. 처음에는 Intersection Observer API를 통해 구현이 가능 할 줄 알았고, 계속 공부하고 적용하려다 보니 해당 기능을 구현하는데 있어서 적절한 API가 아니라고 생각이 되었다. (내가 구현을 못하는 걸 수도 있다..😭) 그러다 구글링을 통해 적절한 코드를 발견했고 스크롤을 위, 아래로 움직일 때 감지할 수 있게 되었다.

var lastScrollTop = 0;
$(window).scroll(function(event){
   var st = $(this).scrollTop();
   if (st > lastScrollTop){
       // downscroll code
   } else {
      // upscroll code
   }
   lastScrollTop = st;
});

코드 출처 - 리뷰나라


 

'use strict';
const header = document.querySelector('header');

function scrollEvent() {
  let lastScrollTop = 8;

  window.addEventListener('scroll', () => {
    let scrollTop = document.documentElement.scrollTop;

    if (scrollTop > lastScrollTop) {
      header.style.transform = 'translateY(-68px)';
    } else {
      header.style.transform = 'translateY(0px)';
    }

    if (scrollTop > 0) {
      header.style.backgroundColor = '#fff';
    } else {
      header.style.backgroundColor = 'transparent';
      scrollTop = 8;
    }

    lastScrollTop = scrollTop;
  });
}

scrollEvent();

위와 같이 기능을 구현했다. 스크롤 이벤트 같은 경우엔 스크롤이 될 때마다 이벤트가 호출되기 때문에 메인 스레드에 부담을 줄 수가 있다. 따라서 성능면에서 좋지 않기 때문에 와이즐리는 코드를 어떻게 작성했을까? 기능 구현을 어떤식으로 했는지, 최적화를 어떻게 했는지 알 방법이 없다. 비슷한 코드나 관련 기능을 구현한 것을 아직은 못봐서 더욱 궁금하다. 🤔

반응형