element.scrollIntoView

IT공부중·2021년 2월 22일
0

frontend

목록 보기
9/16

요즘 웹사이트에서 찾아보면 하나의 페이지만 있고, 상단의 네비게이션 바를 통해 화면을 이동하는 방식을 볼 수 있다. 이러한 페이지는 어떻게 구현하는 것일까? 물론 스크롤을 하나하나 계산해서 이동시킬 수도 있겠지만, element의 메소드인 scrollIntoView를 사용하면 쉽게 구현할 수 있다.

element의 scrollIntoView 메소드는 scrollIntoView가 호출된 요소가 사용자에게 표시되도록 요소의 상위 컨테이너를 스크롤한다.

브라우저 호환성은 다음과 같다. 그냥 기본값으로 사용한다면, IE에서도 사용이 가능할 것 같다.

scrollIntoView의 인자

scrollIntoView는 첫번째 인자로 boolean 값이나, scrollIntoViewOptions 객체를 받을 수 있다.

true 값일 경우에는 { block: 'start', inline: 'nearest'} 와 똑같은 작동한다. 이것이 기본 값이다.

false 일 경우에는 {block: 'end', inline: 'nearest'} 와 같이 작동한다.

scrollIntoViewOptions 객체에는

behavior, block, inline 이라는 속성이 있다.

behavior 은 전한 애니메이션을 정의한다. 기본값은 'auto'이다. 'smooth'를 하면 스크롤이 부드럽게 움직인다.

block 속성은 수직 정렬을 정의한다.

'start', 'center', 'end', 'nearest'가 있고 기본 값은 'start'이다.

inline 속성은 수평정렬을 정의한다.

'start', 'center', 'end,' 'nearest' 중 하나를 선택할 수 있다. 기본 값은 'nearest'이다.

간단한 실습

간단하게 버튼들이 있고, 그 버튼을 누르면 해당 숫자의 화면이 보이는 코드를 짜보았다.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="index.css">
</head>
<body>
    <ul class='phase-button'>
        <li><button>1</button></li>
        <li><button>2</button></li>
        <li><button>3</button></li>
        <li><button>4</button></li>
        <li><button>5</button></li>
        <li><button>6</button></li>
        <li><button>7</button></li>
    </ul>
    <ul class='phase'>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
        <li>7</li>
    </ul>
    <script src='index.js'></script>
</body>
</html>

index.css

* {
  margin: 0;
  padding: 0;
}
.phase-button {
  list-style: none;
  position: fixed;
  top: 0;
  width: 100%;
  display: flex;
  z-index: 2;
}

.phase-button li {
  width: 15%;
  height: 3vh;
}

.phase-button button {
  width: 100%;
  height: 100%;
}

.phase {
  list-style: none;
}

.phase li {
  height: 50vh;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 3rem;
}
.phase li:nth-child(0) {
  background-color: antiquewhite;
}

.phase li:nth-child(1) {
  background-color: red;
}

.phase li:nth-child(2) {
  background-color: blue;
}

.phase li:nth-child(3) {
  background-color: aqua;
}

.phase li:nth-child(4) {
  background-color: teal;
}

.phase li:nth-child(5) {
  background-color: wheat;
}

.phase li:nth-child(6) {
  background-color: aquamarine;
}

index.js

const phaseNav = document.querySelector('.phase-button');
const phaseButtons = document.querySelectorAll('.phase-button button');
const phase = document.querySelectorAll('.phase li');

phaseNav.addEventListener('click', (e) => {
  const target = e.target;
  if (target.tagName !== 'BUTTON') return;

  const targetIndex = Array.from(phaseButtons).indexOf(target);
  phase[targetIndex].scrollIntoView({
    block: 'start',
    behavior: 'smooth',
  });
});

js 코드는 버튼들을 감싸는 ul 태그에 이벤트 위임으로 'click' 이벤트를 달아놓은 것이다.

target에 일치하는 index를 button에서 찾는다. button의 순서와 화면의 순서가 같기 때문에 해당 index element의 위치로 scrollIntoView를 시켜주는 코드이다.

그러면 이런식의 화면을 볼 수 있다.

속성들을 바꾸면서 확인해보았다.

block이 'start' 일 때 3번을 누르면 이렇게 되는 것을 확인할 수 있다.

'end' 일 때는 화면의 끝으로 간다.

'center' 일 때는 가운데로 가는 것을 볼 수 있었다.

'nearest' 일 때는 가장 가까운 곳으로 간다. 위쪽에 가깝다고 판단이 들면 위에 붙어 있고, 밑이 가깝다고 판단되면 밑쪽으로 붙는다.

behavior의 'auto'로 하면 바로 해당 번호로 이동하지만, 'smooth'로 하니 스르륵 하는 효과와 함께 이동하는 것을 확인할 수 있었다.

inline은 수평방향일 때 block과 똑같이 작동할 것 같다.

사용처

scrollIntoView를 활용하면 무엇인가를 판매하는 페이지나, 자기소개를 올려놓는 포트폴리오 페이지 등을 만들 때 수월할 것 같다.

profile
3년차 프론트엔드 개발자 문건우입니다.

3개의 댓글

comment-user-thumbnail
2021년 5월 16일

잘보고갑니다^^ 새로 배우고 가네요

1개의 답글
comment-user-thumbnail
2022년 10월 4일

좋은 정보 감사합니다

답글 달기