JavsCript - Window Sizes & Scrolling

Noma·2021년 1월 28일
0

* javascript.info 자료를 번역 및 일부 첨삭한 내용이다.

이번 포스팅에서는 다음 두 가지를 구하는 방법에 대해 알아보자.

  • 윈도우의 너비
  • 스크롤 되어 사라진 부분을 포함한 전체 문서(document)의 높이

( width와 height의 원리는 동일하므로 예제의 적합성에 따라 window에서는 width를 document에서는 height을 기준으로 작성하겠다. )

이를 위해, <html> 태그에 해당하는 루트 document 요소의 document.documentElement를 사용할 것이다. ( 사용에 예외가 있으나, 밑에서 언급하겠다. )

document.documentElement는 읽기 전용 속성으로 문서의 루트 요소를 나타내는 Element를 반환한다. HTML 문서를 예로 들면 <html> 요소를 반환한다.

1. Window 너비

1.1 document.documentElement.clientWidth

: window의 width는document.documentElementclientWidth을 사용하면 된다. 참고로 clientWidth는 스크롤 바를 포함하지 X

// 예시
alert(document.documentElement.clientWidth);

1.2 Not window.innerWidth !

대부분의 경우, 우리는 무언가를 그리거나 배치하기 위해서 '사용 가능한' (스크롤바를 제외한) window의 너비 및 높이를 필요로 한다.

alert( window.innerWidth ); // full window width
alert( document.documentElement.clientWidth ); // window width - scrollbar 

clientWidth는 스크롤바 제외한 너비를 제공한다. 즉, (content가 이용할 수 있는) 문서의 보여지는 부분의 너비를 반환한다.

그러나, window.innerWidth은 스크롤바를 포함한 값을 반환하므로 사용에 적절하지 않다.

❗ Note
최상위 기하학적 프로퍼티들은 HTML안에 <!DOCTYPE HTML>이 없으면 조금 다르게 작동할 수도 있다. 따라서, 항상 DOCTYPE을 꼭 써야 한다.

2. document 높이

이론상, 루트 document 요소가 document.documentElement이고 이것이 모든 content들을 둘러싸고 있기 때문에, document.documentElement.scrollHeight으로 document의 전체 높이를 측정할 수 있다.

하지만 크롬, 사파리, 오페라에서는 스크롤이 없을 경우(여기선 수직 스크롤) 의도대로 작동하지 않는다.
이 경우, documentElement.scrollHeightdocumentElement.clientHeight보다 작을 수 있다.

따라서 전체 문서 높이를 안정적으로 확보하려면, 다음 속성들의 최대치를 가져오면 된다.

let scrollHeight = Math.max(
  document.body.scrollHeight, document.documentElement.scrollHeight,
  document.body.offsetHeight, document.documentElement.offsetHeight,
  document.body.clientHeight, document.documentElement.clientHeight
);
// ❗ 사파리에서는 document.documentElement대신에 document.body를 써야 한다.
alert(`Full document height, with scrolled out part: ${scrollHeight}`);

3. 현재 스크롤 된 픽셀수 가져오기

X축 스크롤 정보를 얻고 싶을 땐 scrollLeft를 사용하면 되지만, 여기선 Y축 기준으로 살펴 보겠다.

DOM 요소들은 element.scrollTop속성으로, document는document.documentElement.scrollTop으로 대부분의 브라우저에서 현재 수직으로 얼만큼 스크롤 되어 있는지 그 픽셀 수를 알 수 있다.

그러나 사파리에서는 document.documentElement 대신에 document.body를 써줘야 한다는 예외성이 존재한다.

다행히도 이러한 특성에 대해 전혀 기억할 필요가 없이 pageYOffset을 사용하면 된다.

3.1 window.pageYOffset

문서가 수직으로 얼마나 스크롤 됐는지 픽셀 단위로 반환한다.

alert(`Current scroll from the top: ${window.pageYOffset}`);

pageYOffsetscrollY의 다른 이름으로, 일부 오래된 브라우저는 scrollY 대신 pageYOffset만 지원하는 경우가 있지만 노후 환경을 신경쓰지 않아도 된다면 둘 중 아무거나 사용해도 괜찮다.

4. Scrolling

요소나 문서 모두 scrollTop를 변경함으로써 스크롤링 할 수 있지만,

element.scrollTop = intValue; // Set the number of pixels scrolled.

이 외에도 scrollBy(), scrollTo(), scroll(), scrollIntoView()와 같은 더 간단하고 범용적인 솔루션이 있으니 살펴보도록 하자.
→ element, window에서 모두 사용 가능

🌟 참고로 scrollBy( ), scrollTo( ), scroll( )는 다음 두 가지 파라미터를 가진다. (예시는 scrollTo 메소드로 통일)

  • 방법1. ( x좌표, y좌표 )
window.scrollTo(0, 1000);
  • 방법2. ( ScrollToOptions )
window.scrollTo({
  top: 1000,
  left: 0,
  behavior: 'smooth' // behavior에는 'smooth'와 'auto'가 있다.
});

옵션에는 요소를 스크롤할 위치, 스크롤을 smooth하게 할 건지의 여부를 지정하는 속성이 포함되어 있다.

세 가지 메소드 모두 동일한 옵션 사전을 공유한다.

자바스크립트에서 페이지를 스크롤하려면 DOM이 완전히 작성되어져 있어야 한다. 예를 들어,<head>의 스크립트에서 페이지를 스크롤하려고 하면 작동하지 않는다.

4.1 scrollBy( )

'현재 위치'을 기준으로 '상대적'으로 페이지를 스크롤한다.

window.scrollBy(0,100); // 현재 위치에서 페이지를 100px 아래로 스크롤 한다.

4.2 scrollTo( ) , scroll( )

scroll( )scrollTo( )는 지정된 요소 내부의 특정 (절대)좌표로 스크롤 한다. 이는 아래와 같이 scrollTop으로 설정하는 것과 같다.

const element = document.querySelector("#box");

element.scroll(0,50); // x=0, y=50px인 지점으로 스크롤
element.scrollTo(0,50); // ...
element.scrollTop=50; // 모두 같은 결과를 가짐

4.3 scrollIntoView( )

scrollIntoView( )를 호출한 요소가 사용자에게 보이도록 요소의 상위 컨테이너를 스크롤 한다.

예제 )

const element = document.querySelector("#box");

element.scrollIntoView(); // 생략하면 기본값 true로 동작한다.
element.scrollIntoView(false);
element.scrollIntoView({block: "end"});
element.scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"});

Parameter로 다음과 같은 값을 가진다.

1. alignToTop (Optional)

  • true : 요소의 상단이 스크롤 가능한 상위 영역의 맨 위에 정렬되며, true가 기본값이다.
  • false : 요소의 하단이 스크롤 가능한 상위 영역의 맨 아래에 정렬된다.

2. scrollIntoViewOptions (Optional)

  • behavior (Optional) : 에니메이션을 정의
    "auto", "smooth"중 하나 선택, 기본값은 "auto"

  • block (Optional) : 수직 정렬을 정의
    "start", "center", "end", "nearest"중 하나 선택, 기본값은 "start"

  • inline (Optional) : 수평 정렬을 정함
    One of "start", "center", "end", "nearest"중 하나 선택, 기본값은 "nearest"

❗ 참고 자료
https://ko.javascript.info/size-and-scroll-window#page-scroll

profile
Frontend Web/App Engineer

0개의 댓글