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

IT技术 javascript dom
2021-01-12 13:41:57

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

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

这种方法也很麻烦。

6个回答

您可以像这样不遍历 DOM 的情况下获得topleft

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) };
}
这个答案没有考虑父母的抵消。它仅相对于视口
2021-03-15 13:41:57
@Teemoh clientTop / clientLeft 对应于<html>元素上的边框值
2021-03-16 13:41:57
@Nickey 这不是真的——视口位置加上滚动偏移检查,产生相对于整个文档的坐标。
2021-03-24 13:41:57
为什么要减去 clientTop/clientLeft?
2021-03-28 13:41:57
在移动设备上可能有问题stackoverflow.com/a/32623832/962634需要研究
2021-04-03 13:41:57

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

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

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

element.getBoundingClientRect().top + document.documentElement.scrollTop
getBoundingClientRect() 计算元素及其所有后代的边界矩形。如果元素有溢出:可见,它可以有元素布局矩形之外的后代,比自身大的后代,用 CSS 变换任意置换的后代,以及十几种其他边缘情况。
2021-03-16 13:41:57
相对于视口与相对于文档不同。如果页面向下滚动一点,则相对于视口的顶部将比相对于文档的顶部小。
2021-03-20 13:41:57
document.documentElement.scrollTop在 Safari 中不起作用,请window.scrollY改用
2021-03-29 13:41:57
他相对于视口开始并添加 scrollY 以获取它相对于文档。
2021-04-10 13:41:57

您可以遍历offsetParent到 DOM 的顶层。

function getOffsetLeft( elem )
{
    var offsetLeft = 0;
    do {
      if ( !isNaN( elem.offsetLeft ) )
      {
          offsetLeft += elem.offsetLeft;
      }
    } while( elem = elem.offsetParent );
    return offsetLeft;
}
它需要与某些元素相关。只会让您获得全局 offsetLeft。我明白这就是问题,所以我猜对了。我还有另一个案例,它与任何其他父母有关。我想我可以重写这个。谢谢!
2021-03-18 13:41:57
为什么这是公认的答案?这是过时的并且性能不佳。帮自己一个忙,并按照其他答案中的建议使用 getBoundingClientRect() 。
2021-03-23 13:41:57
首先需要根据box-sizing来决定是否考虑border和margin。其次,应考虑折叠边距。最后,未来会出现更复杂的情况,这会使这个答案变得更糟。
2021-03-28 13:41:57
关于边距的东西......它可能有助于将框大小设置为边框框......或沿着这些线的东西......没有什么不能修复......
2021-03-30 13:41:57
不,当任何父元素(尤其是 html 元素!!!)有边距、填充或边框时,它不会。
2021-04-02 13:41:57

我发现以下方法在处理触发 offsetTop/offsetLeft 的边缘情况时是最可靠的。

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

我建议使用

element.getBoundingClientRect()

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

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

应该定义得更高;这些值要有用得多,而且也是一次调用!
2021-03-14 13:41:57
但我发现offsetLeftoffsetTop没有考虑到 CSS3 转换,getBoundingClientRect()确实如此。所以在这种情况下,结果可能无效。如果需要,您可以offsetLeft使用(element.getBoundingClientRect().left - parent.getBoundingClientRect().left).
2021-03-25 13:41:57
您也可以通过将 scrollLeft 和 scrollTop 合并到其中来进行偏移计算。
2021-04-06 13:41:57