查找元素相对于文档的位置


113

确定元素相对于文档/正文/浏览器窗口的位置的最简单方法是什么?

现在,我正在使用.offsetLeft/offsetTop,但是此方法仅给您相对于父元素的位置,因此您需要确定body元素有多少个父元素,以了解相对于body /浏览器窗口/文档位置的位置。

这种方法也很麻烦。

Answers:


60

您可以遍历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 2014年

关于保证金的东西...这可能有助于将框的大小设置为border-box ...或沿这些线的东西...

首先,您需要根据框的大小决定是否考虑边框和边距。其次,应考虑利润率下降。最后,将来还会有更复杂的情况,这将使答案变得更糟。
xianshenglu

5
为什么这是公认的答案?这已过时且效果不佳。帮自己一个忙,并按照其他答案中的建议使用getBoundingClientRect()。
Fabian von Ellerts,

175

你可以得到离开,而无需遍历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 '16

1
可能在移动设备上出现故障stackoverflow.com/a/32623832/962634需要研究
罗勒

1
为什么要减去clientTop / clientLeft?
Teemoh

1
@Teemoh clientTop / clientLeft对应于<html>元素上的边框值。
拉斐尔·拉法帕纳

98

您可以element.getBoundingClientRect()用来检索相对于视口的元素位置。

然后使用document.documentElement.scrollTop来计算视口偏移。

两者之和将给出元素相对于文档的位置:

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

10
相对于视口与相对于文档而言是不同的。如果将页面向下滚动一点,则相对于视口的顶部将小于相对于文档的顶部的数目。
MrVimes 2014年

14
他相对于视口开始,并添加scrollY使其相对于文档。
Joaquin Cuenca Abela

2
document.documentElement.scrollTop不能在Safari中工作,请window.scrollY改用
Fabian von Ellerts,

7

我建议使用

element.getBoundingClientRect()

如此处所建议 而不是通过offsetLeftoffsetTopoffsetParent进行手动偏移计算。如提出这里 在某些情况下*手动遍历产生无效的结果。看到这个柱塞:http ://plnkr.co/pC8Kgj

*当元素位于具有静态(=默认)位置的可滚动父级内部时。


您也可以通过将scrollLeft和scrollTop合并到其中来使偏移量计算工作。
本J

但是我发现了offsetLeftoffsetTop却没有考虑CSS3转换getBoundingClientRect()。因此,结果可能无效。如果需要,您可以使用来获得元素相对于父元素的偏移量(如offsetLeft(element.getBoundingClientRect().left - parent.getBoundingClientRect().left)
Ben J

def应该上升吗?这些值更加有用,而且所有功能都可以一次调用!
mix3d

7

document-offset3rd-party脚本)很有趣,并且似乎可以利用此处其他答案中的方法。

例:

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()函数。如果您想阅读更多有关此功能的信息,请参考文档


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.