JavaScript

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

Vintz 2021. 8. 22. 21:10

와이즐리 헤더 기능 구현

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

한때 와이즐리 사용자로서 이벤트를 하길래 오랜만에 들어와봤다. 옛날과 달리 홈페이지가 엄청 깔끔하고 보기에 편해진 것 같다. 그 중 와이즐리의 헤더 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();

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

반응형