문서를 기준으로 요소의 위치 찾기


113

문서 / 본문 / 브라우저 창을 기준으로 요소 위치를 결정하는 가장 쉬운 방법은 무엇입니까?

지금은를 사용 .offsetLeft/offsetTop하고 있지만이 방법은 부모 요소에 대한 상대적 위치 만 제공하므로 body / 브라우저 창 / 문서 위치에 상대적인 위치를 알기 위해 body 요소에 대한 부모 수를 결정해야합니다.

이 방법도 번거 롭습니다.

답변:


58

offsetParentDOM의 최상위 수준까지 이동할 수 있습니다 .

function getOffsetLeft( elem )
{
    var offsetLeft = 0;
    do {
      if ( !isNaN( elem.offsetLeft ) )
      {
          offsetLeft += elem.offsetLeft;
      }
    } while( elem = elem.offsetParent );
    return offsetLeft;
}

28
아니요, 부모 (특히 html 요소 !!!)에 여백, 패딩 또는 테두리가있는 경우에는 그렇지 않습니다.
Flash Thunder

여백 물건에 관한 것은 ... 그것은 상자 크기 조정 ... 고정 할 수없는 경계 박스 ... 또는 그 라인을 따라 뭔가 ... 아무것도 설정하는 것이 도움이 될 수 있습니다

먼저 상자 크기에 따라 테두리와 여백을 고려할지 여부를 결정해야합니다. 둘째, 접힌 여백을 고려해야합니다. 그리고 마지막으로,이 답변을 더 악화시킬 더 복잡한 상황이 앞으로있을 것입니다.
xianshenglu

6
왜 이것이 허용되는 대답입니까? 이것은 오래되고 성능이 좋지 않습니다. 자신에게 호의를 베풀고 다른 답변에서 제안한대로 getBoundingClientRect ()를 사용하십시오.
Fabian von Ellerts

177

다음 과 같이 DOM을 탐색하지 않고도 상단왼쪽 을 얻을 수 있습니다 .

function getCoords(elem) { // crossbrowser version
    var box = elem.getBoundingClientRect();

    var body = document.body;
    var docEl = document.documentElement;

    var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
    var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;

    var clientTop = docEl.clientTop || body.clientTop || 0;
    var clientLeft = docEl.clientLeft || body.clientLeft || 0;

    var top  = box.top +  scrollTop - clientTop;
    var left = box.left + scrollLeft - clientLeft;

    return { top: Math.round(top), left: Math.round(left) };
}

6
이 답변은 부모의 오프셋을 고려하지 않습니다. 뷰포트에 대해서만 상대적입니다
Nickey

3
@Nickey는 사실이 아닙니다. 뷰포트 위치와 스크롤 오프셋 검사는 전체 문서에 상대적인 좌표를 산출합니다.
natchiketa

1
모바일 장치에서 버그가있을 수 있음 stackoverflow.com/a/32623832/962634 조사 필요
basil

1
clientTop / clientLeft를 빼는 이유는 무엇입니까?
Teemoh

1
@Teemoh clientTop / clientLeft는 <html>요소의 테두리 값에 해당 합니다.
Raphael Rafatpanah

98

를 사용 element.getBoundingClientRect()하여 뷰포트를 기준으로 요소 위치를 검색 할 수 있습니다 .

그런 다음을 사용 document.documentElement.scrollTop하여 뷰포트 오프셋을 계산합니다.

이 둘의 합은 문서에 상대적인 요소 위치를 제공합니다.

element.getBoundingClientRect().top + document.documentElement.scrollTop

10
뷰포트 기준은 문서 기준과 동일하지 않습니다. 페이지가 약간 아래로 스크롤되면 뷰포트에 상대적인 상단이 문서에 대한 상단보다 작은 숫자가됩니다.
MrVimes 2014-06-21

14
그는 뷰포트에 상대적으로 시작하고 scrollY를 추가하여 문서에 상대적으로 가져옵니다.
호아킨 쿠 엥카 아벨라

2
document.documentElement.scrollTop는 Safari에서 작동하지 않습니다. window.scrollY대신 사용
Fabian von Ellerts

7

나는 사용하는 것이 좋습니다

element.getBoundingClientRect()

offsetLeft를 통한 수동 오프셋 계산 대신 여기에 제안 된대로 , offsetTopoffsetParent를 . 여기에 제안 된대로 일부 상황 *에서 수동 순회는 잘못된 결과를 생성합니다. 이 Plunker 참조 : http://plnkr.co/pC8Kgj

* 요소가 정적 (= 기본값) 위치를 갖는 스크롤 가능한 부모 내부에있을 때.


scrollLeft 및 scrollTop을 통합하여 오프셋 계산이 작동하도록 할 수도 있습니다.
Ben J

그러나 나는 발견 offsetLeftoffsetTop계정 CSS3의 변환은 고려하지 getBoundingClientRect()않습니다. 따라서 결과가 유효하지 않을 수 있습니다. 필요한 경우을 offsetLeft사용하여 부모 (예 :)에 상대적인 요소의 오프셋을 가져올 수 있습니다 (element.getBoundingClientRect().left - parent.getBoundingClientRect().left).
Ben J

데프가 더 높아져야합니다. 이 값은 훨씬 더 유용하며 한 번의 호출로도 사용할 수 있습니다!
mix3d

7

document-offset( 타사 스크립트 ) 흥미롭고 여기 다른 답변의 접근 방식을 활용하는 것 같습니다.

예:

var offset = require('document-offset')
var target = document.getElementById('target')
console.log(offset(target))
// => {top: 69, left: 108} 

5

나는 offsetTop / offsetLeft 위로 넘어가는 엣지 케이스를 다룰 때 다음 방법이 가장 신뢰할 수 있음을 발견했습니다.

function getPosition(element) {
    var clientRect = element.getBoundingClientRect();
    return {left: clientRect.left + document.body.scrollLeft,
            top: clientRect.top + document.body.scrollTop};
}

4

문서를 기준으로 한 요소의 다양한 위치에 대한 x 및 y 좌표를 얻으려는 사람들을 위해.

const getCoords = (element, position) => {
  const { top, left, width, height } = element.getBoundingClientRect();
  let point;
  switch (position) {
    case "top left":
      point = {
        x: left + window.pageXOffset,
        y: top + window.pageYOffset
      };
      break;
    case "top center":
      point = {
        x: left + width / 2 + window.pageXOffset,
        y: top + window.pageYOffset
      };
      break;
    case "top right":
      point = {
        x: left + width + window.pageXOffset,
        y: top + window.pageYOffset
      };
      break;
    case "center left":
      point = {
        x: left + window.pageXOffset,
        y: top + height / 2 + window.pageYOffset
      };
      break;
    case "center":
      point = {
        x: left + width / 2 + window.pageXOffset,
        y: top + height / 2 + window.pageYOffset
      };
      break;
    case "center right":
      point = {
        x: left + width + window.pageXOffset,
        y: top + height / 2 + window.pageYOffset
      };
      break;
    case "bottom left":
      point = {
        x: left + window.pageXOffset,
        y: top + height + window.pageYOffset
      };
      break;
    case "bottom center":
      point = {
        x: left + width / 2 + window.pageXOffset,
        y: top + height + window.pageYOffset
      };
      break;
    case "bottom right":
      point = {
        x: left + width + window.pageXOffset,
        y: top + height + window.pageYOffset
      };
      break;
  }
  return point;
};

용법

  • getCoords(document.querySelector('selector'), 'center')

  • getCoords(document.querySelector('selector'), 'bottom right')

  • getCoords(document.querySelector('selector'), 'top center')


2

jQuery를 사용해도 괜찮다면 offset()함수 를 사용할 수 있습니다 . 이 기능에 대한 자세한 내용은 문서를 참조하십시오 .


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.