* 다음은 개발자 홀로 서기 자료를 바탕으로 첨삭 정리한 내용입니다.
해당 그림은 아래 설명에서 전반적으로 계속 사용될 예정이다. 창을 2개 켜서 해당 그림이랑 같이 읽는걸 강력하게 추천한다!
절대위치
: 컨텐츠 시작점으로부터 떨어진 크기 값 ( ① )
상대위치: 어떤 기준(뷰포트 시작 지점 또는 부모 요소의 시작 지점 ..)으로 부터 떨어진 크기 값
기준에 따라 음수 값이 나올 수 있다.
:element.getBoundingClientRect
를 사용하면 구할 수 있다.
이 API는 요소의 크기와 상대 위치(뷰포트 기준)에 대한 정보가 담긴 DOMRect 객체를 반환한다.
DOMRect 객체는 요소(padding 및 border-width를 포함)를 포함하는 가장 작은 직사각형으로, bottom, height, left,...
등의 값이 담겨 있다. width와 height 이외의 특성들은 모두 아래와 같이 뷰포트의 왼쪽 상단을 기준으로 상대적인 값이다.
예제는 아래와 같다.
const target=document.querySelector('#target');
// 요소의 id 값이 target이라 가정
const clientRect=target.getBoundingClientRect();
const relativeTop=clientRect.top;
Viewport 시작 지점을 기준으로한 상대적 Y좌표값이 나온다. ( ② )
Hello Wrold!! 요소라면 음수 값이 나오며, Hello JavaScript!! 요소라면 양수 값이 나올 것이다.
좌표값은 뷰포트 왼쪽 상단(0,0)을 기준으로 ,
X값 - 오른쪽 방향: 양수, 왼쪽 방향: 음수
Y값 - 아래 방향: 양수, 위 방향: 음수
offset
API 시리즈를 사용하면 구할 수 있는데, 이는 부모 요소의 포지셔닝 정책이 무엇이냐에 따라 위치값이 달라지므로 조금 복잡하다.
offset API 시리즈에는
offsetTop, offsetLeft, offsetWidth, offsetHeight
등이 있다.
해당 API는 부모가 position: static
이면 position:relative
인 요소를 만날 때까지 상위 요소의 포지셔닝을 탐색한다. 만약 상위 요소들이 전부 static
이면 결국 offsetTop API는 컨텐츠의 시작 지점 즉, 절대위치 값을 리턴하게 된다.
❗ Note
사양에따라, 이 속성은 요소가display:hidden
이거나 어떠한 조상도 없거나, 요소 자체가position:fixed
인 경우 웹킷에서는 null을 반환한다.
따라서, 부모 요소를 기준으로 한 상대위치는 부모의 '절대 위치'와 자식의 '절대위치'를 구해 두 값을 연산하여 구하는 것이 가장 안전하다.
그 방법은 절대좌표 구하기 섹션을 진행한 후 다시 보도록 하자.
대부분 offset API로 절대좌표를 구하지만, 위에서 설명했듯이 포지셔닝 정책에 따라 구해지는 값이 달라지므로 안전하게 구하는 방법을 알아보자.
Hellot World!의 절대좌표를 구한다고 하면, ①번 길이를 구해야 한다. 이는 아래와 같이 구할 수 있다.
①번 길이 = ③번 길이 - ②번
즉, 스크롤된 컨텐츠의 길이와 viewport 기준의 상대좌표를 연산하여 구한다는 것이다.
이해했다면 아래 코드를 보자.
const target = document.getElementById('target');
// 요소의 id 값이 target이라 가정
const clientRect = target.getBoundingClientRect();
// DomRect 구하기 (각종 좌표값이 들어있는 객체)
const relativeTop = clientRect.top;
// Viewport의 시작지점을 기준으로한 상대좌표 Y 값.
const scrolledTopLength = window.pageYOffset;
// 스크롤된 길이
const absoluteTop = scrolledTopLength + relativeTop;
// : 🌟절대좌표!!
위의 설명을 토대로, 상황에 상관없이 안전하게 값을 구할 수 있는 예시를 정리해보고 마치도록 하자.
const absoluteTop=window.pageYOffset+element.getBoundingClientRect().top;
const relativeTop=element.getBoundingClientRect().top;
function getAbsoluteTop(element){
return window.pageYOffset+element.getBoundingClientRect().top;
}
const parentElement=element.parentElement;
const parentAbsoluteTop=getAbsoluteTop(parentElement);
const absoluteTop=getAbsoluteTop(element);
const relativeTop=absoluteTop-parentAbsoluteTop;
❗ 참고 자료
https://mommoo.tistory.com/85
https://javascript.info/coordinates