요소가 지금 뷰포트(Viewport) 안 어디에 얼마만 한 크기로 그려져 있는지를 DOMRect(x, y, top, right, bottom, left, width, height)로 돌려주는 DOM(Document Object Model) API. 문서 기준이 아니라 현재 화면 기준이다.
const r = el.getBoundingClientRect()
r.top // 화면 위쪽에서의 거리 (스크롤하면 바뀜)
r.top + window.scrollY // 문서 기준 위치- 스크롤을 내리면
top이 줄어든다. 대략top = 문서상 위치 - 스크롤 위치 width·height는 소수점을 포함하고transform이 반영된 실제 그려진 크기다.offsetWidth는 정수이고 transform 적용 전 레이아웃 크기다.transform: scale(2)인 100px 상자는offsetWidth100,getBoundingClientRect().width200이다- 호출하면 미뤄 둔 스타일 변경을 반영하느라 레이아웃이 강제로 일어날 수 있다. DOM을 바꾸면서 반복해서 부르면 레이아웃 스래싱이 된다
쓰임
// 툴팁을 버튼 바로 아래에
const b = button.getBoundingClientRect()
tip.style.left = `${b.left}px`
tip.style.top = `${b.bottom + 8}px`
// 두 상자가 겹치는지(드래그 앤 드롭 충돌 검사)
const hit = a.left < b.right && a.right > b.left && a.top < b.bottom && a.bottom > b.top- "요소가 화면에 들어왔는지"는 스크롤 이벤트마다 이 값을 재는 대신 IntersectionObserver가 낫다. 브라우저가 레이아웃을 강제하지 않고 알려 준다
- React에서 측정한 값으로 위치를 바로 고쳐야 한다면 페인트 전에 실행되는 useLayoutEffect에서 읽어야 깜빡임이 없다. 겹쳐 띄우는 UI는 포털과 함께 쓰는 경우가 많다
- 큰 목록에서 어떤 항목이 보이는지 계산하는 가상 스크롤(Virtual Scrolling)도 같은 좌표 계산을 쓴다