Javascript

Javascript30 - day24 Sticky Nav

joy_lee 2021. 4. 28. 22:32

목표

sticky nav 만들기(position: sticky를 사용하지 않음)

nav가 맨 위에 있을 때, 왼쪽의 로고가 나타나도록 한다.

 

내가 만든 코드

1
2
3
4
5
6
7
8
9
10
11
12
const nav = document.querySelector('nav');
const logo = document.querySelector('.logo');
 
function setStickyNav(e) {
  nav.style.position = "sticky";
  const navTopCoord = nav.getBoundingClientRect().top;
  if (navTopCoord <= 0) {
    logo.style.maxWidth = '100%';
  }
}
 
window.addEventListener('scroll', setStickyNav);
cs

 

목표를 잘 이해하지 못해서 positioin = sticky를 사용했다.

position = sticky를 사용하면 굳이 scroll event를 사용할 필요가 없다. 처음부터 nav style이 position=sticky;이면 원하는 sticky nav를 구현할 수 있다.

getBoundingClientRect()를 통해 screen에서의 nav의 위치를 알아내서 logo를 나타나게 하려고 했는데 잘 되지 않았다.

 

영상에서 나온 코드

1
2
3
4
const nav = document.querySelector('#main');
const topOfNav = nav.offsetTop;
 
window.addEventListener('scroll', fixNav);
cs

class name을 통해 nav를 선택해준다.

nav가 얼마나 움직인 후에 position=fixed;될지 알려면 nav의 offsetTop을 알아야 한다.

window.addEventListener를 통해 스크롤 할 때마다 fixNav함수를 실행하도록 한다.

 

 

1
2
3
4
5
6
7
8
9
function fixNav() {
  if(window.scrollY >= topOfNav) {
    document.body.classList.add('fixed-nav');
    document.body.style.paddingTop = nav.offsetHeight + 'px';
  } else {
    document.body.classList.remove('fixed-nav');
document.body.style.paddingTop = 0;
  }
}
cs

fixNav 함수에서는 window.scrollY와 topOfNav를 비교한다.

window.scrollY >= topOfNav인 경우는 nav의 위치보다 화면이 더 아래로 내려간 경우이므로 nav를 fix시켜야한다.

nav.style.position = fixed;로 할 수 있다. 하지만 body에 class를 추가하면 한 번의 classList.add로 body의 여러 child를 조정할 때 유용하다.

Class를 각각 추가해준 경우

CSS 설정

Body

 header

  nav (.fixed-nav)

 site-wrap (.fixed-site-wrap)

.fixed-nav { }
.fixed-site-wrap { }

ClassBody에만 추가해준 경우

CSS 설정

Body (.fixed-nav)

 header

  nav

 site-wrap

.fixed-nav nav { }
.fixed-nav site-wrap { }

nav의 position이 바뀌면 더이상 그 자리를 차지하지 않아서 갑자기 .site-wrap이 올라가는 것 처럼 보인다

nav.offsetHeight로 높이를 가져와서 공백을 만들어준다.

CSS에서 바로 .fixed-nav body 설정으로 바꿔주지 않았다. nav.offsetHeight를 통해 값을 가져오면 nav의 높이가 변해도 유연하게 설정을 변경해줄 수 있기 때문이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.fixed-nav nav {
  position: fixed;
  box-shadow: 0 5px rgba(0, 0, 0, 0.1);
}
 
.site-wrap {
  (...)
  transform: scale(0.98);
  transition: transform 0.5s;
}
 
.fixed-nav .site-wrap {
  transform: scale(1);
}
 
li.logo {
  max-width: 0;
  (...)
}
 
.fixed-nav li.logo {
  /* transition을 위해서는 max-width을 사용해야 한다 */
  max-width: 500px;
}
cs

.fixed-nav nav에서 position : fixed;로 바꿔준다.

.site-wrap은 원래 transform: scale(0.98);이었는데 .fixed-nav .site-wrap 에서 scale(1);로 바꿔서 사소한 변화를 추가한다.

li.logo는 max-width:0; 에서 max-width: 500px;로 바꿔줬는데 width:0;에서 width: 500px;는 logo가 사라졌다가 나타나지 않는다. 우리가 원하는 애니메이션 효과를 만들기 위해서는 max-width 설정으로 조절해줘야 한다.

 

새롭게 알게된 사실

같은 조건에서 하위 여러 요소를 한꺼번에 변화시키고 싶을때 -> 상위 요소에 클래스를 추가해서 사용한다.

position: fixed;가 되면 다른 z-index를 가지는 것으로 인식되어 원래 있던 위치에서 사라진다 -> 아래에 있던 element들이 빈 자리를 채워 올라오는 것 같이 된다.