navbar scroll시 에러 해결 / 메뉴고정 및 색 변경

holang-i·2021년 4월 28일
1

화면에서 스크롤을 하면, 보통 화면 상단에 위치한 메뉴가 사라질까?

사라지게 구현한다면, 스크롤 시 메뉴를 사라지게 했다가 마우스를 화면의 상단으로 가져가면, 메뉴가 나타나도록 구현할 수 있을 것이다.

이번에 구현하려고하는 기능은 메뉴가 상단에 위치해 있고, background-color는 투명이었다가 화면의 스크롤이 일어나면, 기존에 자리를 차지하고 있던 크기에서 영역을 조금 줄이고, 배경색을 연하게 넣어서 계속해서 메뉴 상단에 보여주려고 한다.

그러면, 생각해야 되는 것들이 무엇이 있을까?

1. scrolling되면 얼만큼 내려갔을 때 navbar를 어떻게 처리 할 것인지?

--> background-color는 분홍색으로 변경해보려고 한다.

2. 먼저 navbar의 height을 구해야 된다.

--> window가 scrolling 될 때 navbar의 height만큼 스크롤링이 이루어지면, 배경 바꾸기!


Window.scrollY

https://developer.mozilla.org/ko/docs/Web/API/Window/scrollY

scrollY는 윈도우에 있는 property로 읽기만 가능하고, 문서가 수직으로 얼마나 스크롤되는지를 px단위로 반환해준다.
반드시 정수값을 반환하지는 않기때문에 정숫값이 필요할 경우 Math.round( )를 사용해서 반올림하여 사용하면 된다.

document.addEventListener('scroll', () => {
  let y = window.scrollY
  console.log(y);
});

위의 코드는 통해 해당 화면에서 스크롤이 발생하지 않았을 때 0px부터 스크롤을 밑으로 내렸다가 화면의 맨 위로 다시 올렸을 때의 실행 코드이다.

Window.scrollY를 사용해서 화면의 스크롤 여부와 해당 위치를 파악할 수 있는 것을 확인했다.


메뉴 보였다 안 보였다 처리! 이게 정확할까?

Window.scrollY를 이용해서 스크롤되는 화면의 위치를 구해놓고, 내가 만들어 놓은 페이지의 메뉴를 기준으로 마우스 스크롤을 내리면서 투명색이었던 메뉴를 background-color로 색을 지정하기 위해 조건문을 이용해서 구현했다.

document.addEventListener('scroll', () => {
  let y = window.scrollY;
  console.log(y);
  if (y > 45) {
    nav.style.backgroundColor = 'pink';
    nav.style.width = '100%';
  } else {
    nav.style.backgroundColor = 'transparent';
  }
});

위에 방법처럼 구현은 했지만, 뭔가 이게 정말 좋게 구현한 건지.. 작동이 되면 장땡이 아니라 좋은 방법, 정확한 방법을 최대한 적용하고 싶은 생각이 있었기 때문에 검색을 더 해보고, 알아본 결과 엘리먼트의 너비와 높이를 알기 위해 사용할 수 있는 방법이 있다는 것을 찾아냈다.


Determining the dimensions of elements

https://developer.mozilla.org/ko/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements

navbar의 height을 알아내기 위해서 html element size를 검색해서 알아보았다.

element의 width, height를 알기 위해 살펴볼 수 있는 여러 속성들이 있다. 그리고, 각각 요구하는 사항에 딱 맞는 것을 고르기 까다로울 수 있기 때문에 아래의 방법들 중 필요에 따라 사용할 수 있는 것들을 직접 사용하면서 방법을 익혀야겠다고 생각했다.


offsetWidth & offsetHeight

표시된 contentd의 width, height, scrollbar, padding까지 포함해서 element가 차지하는 전체 공간을 알고 싶을 때 사용


clientWidth & clientHeight

padding은 포함하고, border, margin, scrollbar는 포함시키지 않고 보이는 content가 실제로 차지하는 공간이 알고 싶을 때 사용


scrollWidth & scrollHeight

content의 실제 크기를 알고 싶을 때(보여지는 부분만이 아닌 전체 content크기), 이 속성들은 element content의 전체 크기에 해당하는 너비와 높이를 반환한다. 보여지는 영역이 작아서 스크롤바를 사용하고 있다해도 상관없다.


Element.getBoundingClientRect()

DOMRect: 직사각형의 크기와 위치를 나타냅니다.

viewport: 현재 보고있는 컴퓨터 그래픽의 다각형(일반적으로 직사각형) 영역을 나타내고, 웹 브라우저에서는 현재 창 (또는 문서를 전체 화면 모드로 보는 경우 화면)에 표시되는 현재 보고있는 문서의 일부를 나타낸다.
뷰포트 외부의 콘텐츠는 스크롤 할 때까지 화면에 표시되지 않는다.


Element.getBoundingClientRect() 메서드는 DOMRect 요소의 크기 및 뷰포트를 기준으로 한 위치에 대한 정보를 제공하는 객체를 반환한다.

한 위치에 대한 정보를 제공하는 객체를 반환한다!
--> 그렇다면 기준이 되는 것을 정해주면, 그 기준에 대한 위치 정보를 얻을 수 있겠네? 생각할 수 있다.


nevbar.getBoundingClientRect().height

  • 반환 된 값은 DOMRect 패딩 및 테두리 너비를 포함하여 전체 요소를 포함하는 가장 작은 사각형인 객체입니다.
  • left, top, right, bottom, x, y, width, 및 height특성은 화소의 전반적인 직사각형의 위치 및 사이즈를 설명한다.
  • width 및 이외의 속성 height은 뷰포트의 왼쪽 상단을 기준으로합니다.

수정한 코드

document.addEventListener('scroll', () => {
  const scrollY = window.scrollY;
  const menuY = nav.getBoundingClientRect().height;
  console.log(scrollY);
  console.log(menuY);

  if (scrollY > menuY) {
    nav.classList.add('navbar--dark');
    // navbar.style.backgroundColor = 'pink';
    // navbar.style.width = '100%';
  } else {
    nav.classList.remove('navbar--dark');
    // navbar.style.backgroundColor = 'transparent';
  }
});

위의 코드가 getBoundingClientRect()객체의 height를 구해서 스크롤 했을 때 scrollY가 menuY를 넘는 순간 처리하는 식으로 코드를 수정했다.

위에서 이 방법을 사용하기전에도 틀렸다고는 할 수 없지만, 매번 scrollY의 영역을 구해서 고정된 숫자로 비교하는 것은 좋지 않다고 생각했기 때문에 이 방법이 훨씬 다양한 프로젝트에 적용할 때 좋은 코드라 생각했다.

profile
🌿 주니어 프론트엔드 개발자입니다! 부족하거나 잘못된 정보가 있다면 알려주세요:)

0개의 댓글