检索 HTML 元素的位置 (X,Y)

Retrieve the position (X,Y) of an HTML element

提问人: 提问时间:1/14/2009 最后编辑:Dorian 更新时间:7/16/2023 访问量:2315338

问:

我想知道如何在 JavaScript 中获取 HTML 元素(例如 和 )的 X 和 Y 位置。imgdiv

JavaScript HTML CSS DOM 位置

评论

8赞 Jayapal Chandran 4/2/2015
我一直在使用这 7 行代码,这些代码适用于所有浏览器,但在 IE5、6、7 中存在差异(我不记得有任何 proboem......可能是文档类型)......quirksmode.org/js/findpos.html 和我已经用了这么多年了。如果有的话,可能是 sombody 可以指出缺陷。
125赞 Motomotes 5/27/2015
@AnthonyWJones,我想你需要迂腐的乐趣,但很明显,在未指定时总是如此,OP 指的是最一般的情况,或者指的是浏览器的窗口坐标。
18赞 Andre Figueiredo 10/22/2017
@Mote,不,没那么明显。把推理、主观性和虚假公理放在一边。它可以是相对于视口或页面顶部的(又名 document.documentElement)。
21赞 Motomotes 10/23/2017
默认为最一般的不是推理,而是逻辑进展,因此这将是相对于窗口而言的,或者“页面顶部”可能是您所说的术语。在博弈论中,它被编纂为一个称为谢林点的概念。请务必指定何时不是最一般的情况。
9赞 Andre Figueiredo 1/23/2019
关键是,对某些人来说显而易见,对另一些人来说并不明显。即使理论上我们知道是哪种情况,但由于经验知识,清晰度不会伤害这里的任何人,特别是对于那些刚开始编程的人来说。

答:

66赞 AnthonyWJones 1/14/2009 #1

大多数浏览器上的 HTML 元素将具有:-

offsetLeft
offsetTop

这些指定元素相对于其最近具有布局的父元素的位置。通常可以通过 offsetParent 属性访问此父级。

IE 和 FF3 有

clientLeft
clientTop

这些属性不太常见,它们指定具有其父工作区的元素位置(填充区域是工作区的一部分,但边框和边距不是)。

14赞 Shalom Craimer 1/14/2009 #2

使用 JavaScript 框架可能会更好地服务于您,该框架具有以独立于浏览器的方式返回此类信息(以及更多!这里有几个:

使用这些框架,您可以执行以下操作:获取图像的 y 像素坐标。$('id-of-img').top

374赞 meouw 1/14/2009 #3

这些库会竭尽全力为元素获取准确的偏移量。
这是一个简单的函数,可以在我尝试过的所有情况下完成这项工作。

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}
var x = getOffset( document.getElementById('yourElId') ).left; 

评论

16赞 Adam 7/30/2009
将: el = el.parentNode 更改为: el = el.offsetParent;它现在似乎适用于嵌套的 iframe......我想这就是你的本意?
0赞 Jordash 6/2/2022
测试了这一点,即使存在缩放级别,它也能很好地工作!
8赞 John_ 1/14/2009 #4

如果使用 jQuery,dimensions 插件非常出色,允许您准确指定所需的内容。

例如:

相对位置、绝对位置、无填充的绝对位置、带填充......

它继续下去,让我们说你可以用它做很多事情。

此外,使用 jQuery 的好处是它的文件大小轻巧且易于使用,之后您不会在没有它的情况下返回 JavaScript。

39赞 Refik Ayata 8/13/2010 #5

如果页面至少包含任何“DIV”,则 meouw 给出的函数会抛出超出当前页面限制的“Y”值。为了找到确切的位置,您需要同时处理 offsetParent 和 parentNode。

尝试下面给出的代码(已检查FF2):


var getAbsPosition = function(el){
    var el2 = el;
    var curtop = 0;
    var curleft = 0;
    if (document.getElementById || document.all) {
        do  {
            curleft += el.offsetLeft-el.scrollLeft;
            curtop += el.offsetTop-el.scrollTop;
            el = el.offsetParent;
            el2 = el2.parentNode;
            while (el2 != el) {
                curleft -= el2.scrollLeft;
                curtop -= el2.scrollTop;
                el2 = el2.parentNode;
            }
        } while (el.offsetParent);

    } else if (document.layers) {
        curtop += el.y;
        curleft += el.x;
    }
    return [curtop, curleft];
};

评论

1赞 rob 5/13/2014
与其他解决方案一样,即使使用 FF 24.4,当边框宽度作为定位布局的一部分存在时,上述代码也不起作用。
0赞 Will Byrne 6/11/2015
你是救命恩人。我现在正在解决一些非常深的 GWT 错误,并将其放入 JSNI 方法中可以解决我所有的问题!
17赞 akauppi 8/18/2010 #6

jQuery .offset() 将获取第一个元素的当前坐标,或设置匹配元素集中每个元素相对于文档的坐标。

评论

1赞 Abdul Rahim Haddad 8/11/2013
由于某种原因,与其他浏览器相比,它在 IE 中给出的结果并不相同。我认为在 IE 中它给出了相对于窗口的位置,所以如果你滚动,你会在 IE 中获得与其他结果不同的结果
1赞 Timo Kähkönen 6/1/2015
offset() 被缩放混淆了,至少在 Android Chrome 中是这样,所以它没用。stackoverflow.com/a/11396681/1691517 显示了缩放容忍方式。
7赞 Ron Reiter 9/11/2011 #7

这是我设法创建的最好的代码(也适用于 iframe,与 jQuery 的 offset() 不同)。似乎 webkit 的行为有点不同。

根据 meouw 的评论:

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        // chrome/safari
        if ($.browser.webkit) {
            el = el.parentNode;
        } else {
            // firefox/IE
            el = el.offsetParent;
        }
    }
    return { top: _y, left: _x };
}

评论

2赞 S P 3/7/2012
请注意,您需要 jQuery 才能使用 ;您需要尝试使用纯 .$.browser.webkitnavigator.userAgentJavaScript
4赞 Gus 1/13/2014
$.browser 在最新版本的 jQuery 中不再可用
1赞 rob 5/13/2014
不幸的是,即使使用 FF 24.4,当边框宽度作为定位布局的一部分存在时,上述代码也不起作用。
37赞 ThinkingStiff 1/14/2012 #8

您可以添加两个属性来获取任何元素的顶部/左侧。Element.prototype

Object.defineProperty( Element.prototype, 'documentOffsetTop', {
    get: function () { 
        return this.offsetTop + ( this.offsetParent ? this.offsetParent.documentOffsetTop : 0 );
    }
} );

Object.defineProperty( Element.prototype, 'documentOffsetLeft', {
    get: function () { 
        return this.offsetLeft + ( this.offsetParent ? this.offsetParent.documentOffsetLeft : 0 );
    }
} );

这是这样称呼的:

var x = document.getElementById( 'myDiv' ).documentOffsetLeft;

下面是一个将结果与 jQuery 和 : http://jsfiddle.net/ThinkingStiff/3G7EZ/offset().top.left

评论

17赞 Jared Forsyth 6/23/2015
修改通常被认为是一个坏主意。这导致代码维护非常困难。此外,此代码不考虑滚动。Element.prototype
2440赞 Andy E 7/9/2012 #9

正确的方法是使用 element.getBoundingClientRect():

var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);

只要您可能关心,Internet Explorer 就一直支持这一点,并且它最终在 CSSOM 视图中标准化。所有其他浏览器很久以前就采用了它。

某些浏览器还返回 height 和 width 属性,尽管这是非标准的。如果您担心较旧的浏览器兼容性,请查看此答案的修订版,以优化降级实现。

返回的值是相对于视口的。如果您需要相对于另一个元素的它,只需从另一个矩形中减去一个矩形:element.getBoundingClientRect()

var bodyRect = document.body.getBoundingClientRect(),
    elemRect = element.getBoundingClientRect(),
    offset   = elemRect.top - bodyRect.top;

alert('Element is ' + offset + ' vertical pixels from <body>');

评论

193赞 Déjà vu 2/19/2014
一篇关于JS坐标的非常有趣的文章。这篇文章在 SO 上没有提及,它应该......
13赞 Martynas Jusevičius 3/8/2022
BoundingClientRect滚动时的更改
9赞 Adam Boostani 4/16/2013 #10

如果您使用的是jQuery,这可能是一个简单的解决方案:

<script>
  var el = $("#element");
  var position = el.position();
  console.log( "left: " + position.left + ", top: " + position.top );
</script>
26赞 Abdul Rahim Haddad 7/26/2013 #11

要有效地检索相对于页面的位置,并且不使用递归函数:(也包括 IE)

var element = document.getElementById('elementId'); //replace elementId with your element's Id.
var rect = element.getBoundingClientRect();
var elementLeft,elementTop; //x and y
var scrollTop = document.documentElement.scrollTop?
                document.documentElement.scrollTop:document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft?                   
                 document.documentElement.scrollLeft:document.body.scrollLeft;
elementTop = rect.top+scrollTop;
elementLeft = rect.left+scrollLeft;

评论

0赞 scunliffe 12/7/2014
包括所有重要的 scrollTop/scrollLeft 使这个答案更加正确。
1赞 Duncan 10/12/2014 #12

只是以为我也会把它扔在那里。
我无法在较旧的浏览器中测试它,但它可以在前 3 名中的最新浏览器中运行。:)

Element.prototype.getOffsetTop = function() {
    return ( this.parentElement )? this.offsetTop + this.parentElement.getOffsetTop(): this.offsetTop;
};
Element.prototype.getOffsetLeft = function() {
    return ( this.parentElement )? this.offsetLeft + this.parentElement.getOffsetLeft(): this.offsetLeft;
};
Element.prototype.getOffset = function() {
    return {'left':this.getOffsetLeft(),'top':this.getOffsetTop()};
};
2赞 Mark Espinoza 10/23/2014 #13

我成功地使用了 Andy E 的解决方案,根据用户单击表行中的哪个链接来定位 bootstrap 2 模态。该页面是 Tapestry 5 页面,下面的 javascript 是在 java 页面类中导入的。

JavaScript的:

function setLinkPosition(clientId){
var bodyRect = document.body.getBoundingClientRect(),
elemRect = clientId.getBoundingClientRect(),
offset   = elemRect.top - bodyRect.top;
offset   = offset + 20;
$('#serviceLineModal').css("top", offset);

}

我的模态代码:

<div id="serviceLineModal" class="modal hide fade add-absolute-position" data-backdrop="static" 
 tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="top:50%;">
<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
    <h3 id="myModalLabel">Modal header</h3>
</div>

<div class="modal-body">
    <t:zone t:id="modalZone" id="modalZone">
        <p>You selected service line number: ${serviceLineNumberSelected}</p>
    </t:zone>
</div>

<div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    <!-- <button class="btn btn-primary">Save changes</button> -->
</div>

循环中的链接:

<t:loop source="servicesToDisplay" value="service" encoder="encoder">
<tr style="border-right: 1px solid black;">       
    <td style="white-space:nowrap;" class="add-padding-left-and-right no-border"> 
        <a t:type="eventLink" t:event="serviceLineNumberSelected" t:context="service.serviceLineNumber" 
            t:zone="pageZone" t:clientId="modalLink${service.serviceLineNumber}"
            onmouseover="setLinkPosition(this);">
            <i class="icon-chevron-down"></i> <!-- ${service.serviceLineNumber} -->
        </a>
    </td>

还有 page 类中的 java 代码:

void onServiceLineNumberSelected(String number){
    checkForNullSession();
    serviceLineNumberSelected = number;
    addOpenServiceLineDialogCommand();
    ajaxResponseRenderer.addRender(modalZone);
}

protected void addOpenServiceLineDialogCommand() {
    ajaxResponseRenderer.addCallback(new JavaScriptCallback() {
        @Override
        public void run(JavaScriptSupport javascriptSupport) {
            javascriptSupport.addScript("$('#serviceLineModal').modal('show');");
        }
    });
}

希望这对某人有所帮助,这篇文章有所帮助。

评论

1赞 Brad Martin 8/15/2015
这个 js 代码帮助了我,我有一个旧的 webforms 应用程序使用多个占位符注入 .aspx 页面,我无法弄清楚如何附加我正在创建的弹出框的 Child() 以将其放入视口,因为整个 DOM 树都与多个占位符和不正确的标记有关。使用 body.getBoundingClientRect() 然后在定位中使用它的顶部是我所需要的。谢谢。
7赞 James Montagne 11/4/2014 #14

我发现的最干净的方法是jQuery使用的技术的简化版本。与其他一些答案类似,它以 ;然后,它使用 和 来调整滚动位置以及 上的边距(通常是默认值)。offsetgetBoundingClientRectwindowdocumentElementbody

var rect = el.getBoundingClientRect();
var docEl = document.documentElement;

var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;

var els = document.getElementsByTagName("div");
var docEl = document.documentElement;

for (var i = 0; i < els.length; i++) {

  var rect = els[i].getBoundingClientRect();

  var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
  var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;

  els[i].innerHTML = "<b>" + rectLeft + ", " + rectTop + "</b>";
}
div {
  width: 100px;
  height: 100px;
  background-color: red;
  border: 1px solid black;
}
#rel {
  position: relative;
  left: 10px;
  top: 10px;
}
#abs {
  position: absolute;
  top: 250px;
  left: 250px;
}
<div id="rel"></div>
<div id="abs"></div>
<div></div>

0赞 samadadi 1/9/2015 #15

由于不同的浏览器以不同的方式呈现边框、填充、边距等。我写了一个小函数来检索您想要的精确维度的每个根元素中特定元素的顶部和左侧位置:

function getTop(root, offset) {
    var rootRect = root.getBoundingClientRect();
    var offsetRect = offset.getBoundingClientRect();
    return offsetRect.top - rootRect.top;
}

要检索左侧位置,您必须返回:

    return offsetRect.left - rootRect.left;
475赞 Adam Grant 1/30/2015 #16

此函数返回元素相对于整个文档(页面)的位置:

function getOffset(el) {
  const rect = el.getBoundingClientRect();
  return {
    left: rect.left + window.scrollX,
    top: rect.top + window.scrollY
  };
}

使用它,我们可以得到 X 位置:

getOffset(element).left

...或 Y 位置:

getOffset(element).top

评论

2赞 Richard Scarrott 1/12/2023
如果元素位于许多嵌套的可滚动元素中,该怎么办?我认为您需要递归考虑每个父元素的 scrollLeft / scrollTop?
5赞 Bojan Kseneman 3/15/2015 #17

我这样做是为了与旧浏览器交叉兼容。

// For really old browser's or incompatible ones
    function getOffsetSum(elem) {
        var top = 0,
            left = 0,
            bottom = 0,
            right = 0

         var width = elem.offsetWidth;
         var height = elem.offsetHeight;

        while (elem) {
            top += elem.offsetTop;
            left += elem.offsetLeft;
            elem = elem.offsetParent;
        }

         right = left + width;
         bottom = top + height;

        return {
            top: top,
            left: left,
            bottom: bottom,
            right: right,
        }
    }

    function getOffsetRect(elem) {
        var box = elem.getBoundingClientRect();

        var body = document.body;
        var docElem = document.documentElement;

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

        var clientTop = docElem.clientTop;
        var clientLeft = docElem.clientLeft;


        var top = box.top + scrollTop - clientTop;
        var left = box.left + scrollLeft - clientLeft;
        var bottom = top + (box.bottom - box.top);
        var right = left + (box.right - box.left);

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

    function getOffset(elem) {
        if (elem) {
            if (elem.getBoundingClientRect) {
                return getOffsetRect(elem);
            } else { // old browser
                return getOffsetSum(elem);
            }
        } else
            return null;
    }

有关 JavaScript 中坐标的更多信息,请访问:http://javascript.info/tutorial/coordinates

1赞 Jay Byford-Rew 6/18/2015 #18

经过大量研究和测试,这似乎有效

function getPosition(e) {
    var isNotFirefox = (navigator.userAgent.toLowerCase().indexOf('firefox') == -1);
    var x = 0, y = 0;
    while (e) {
        x += e.offsetLeft - e.scrollLeft + (isNotFirefox ? e.clientLeft : 0);
        y += e.offsetTop - e.scrollTop + (isNotFirefox ? e.clientTop : 0);
        e = e.offsetParent;
    }
    return { x: x + window.scrollX, y: y + window.scrollY };
}

查看 http://jsbin.com/xuvovalifo/edit?html,js,output

11赞 James Carlyle-Clarke 12/1/2015 #19

我采用了@meouw的答案,在允许边框的clientLeft中添加,然后创建了三个版本:

getAbsoluteOffsetFromBody - 与@meouw类似,它获取相对于文档的正文或 html 元素的绝对位置(取决于 quirks 模式)

getAbsoluteOffsetFromGivenElement - 返回相对于给定元素 (relativeEl) 的绝对位置。请注意,给定元素必须包含元素 el,否则其行为将与 getAbsoluteOffsetFromBody 相同。如果在另一个(已知)元素中包含两个元素(可选为节点树上的几个节点)并希望使它们处于相同的位置,这将非常有用。

getAbsoluteOffsetFromRelative - 返回相对于第一个父元素的绝对位置,位置为:relative。出于同样的原因,这类似于 getAbsoluteOffsetFromGivenElement,但只会延伸到第一个匹配元素。

getAbsoluteOffsetFromBody = function( el )
{   // finds the offset of el from the body or html element
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

getAbsoluteOffsetFromGivenElement = function( el, relativeEl )
{   // finds the offset of el from relativeEl
    var _x = 0;
    var _y = 0;
    while( el && el != relativeEl && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

getAbsoluteOffsetFromRelative = function( el )
{   // finds the offset of el from the first parent with position: relative
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
        if (el != null)
        {
            if (getComputedStyle !== 'undefined')
                valString = getComputedStyle(el, null).getPropertyValue('position');
            else
                valString = el.currentStyle['position'];
            if (valString === "relative")
                el = null;
        }
    }
    return { top: _y, left: _x };
}

如果您仍然遇到问题,尤其是与滚动有关的问题,您可以尝试查看 http://www.greywyvern.com/?post=331 - 我注意到 getStyle 中至少有一段有问题的代码,假设浏览器行为良好,这应该没问题,但根本没有测试其余的。

评论

0赞 Norman 1/14/2018
有趣。。。但在 Edge 上,getAbsoluteOffsetFromBody(element).top 在我滚动时返回不同的值,在 Chrome 中,当我滚动时它保持一致。似乎 Edge 正在调整滚动位置。当元素滚动到视图之外时,我得到一个负值。
0赞 Nolyurn 8/13/2018
getAbsoluteOffsetFromRelative 让我很开心,我不得不在没有 Javascript 的情况下重现引导工具提示,这对我有很大帮助。
0赞 Mukyuu 1/10/2020
以防万一,如果 Meouw 更改了他们的用户名,请链接到答案:stackoverflow.com/a/442474/3654837。(我不想碰到这个旧线程,所以是的,我发表评论)
10赞 KingRider 8/25/2016 #20

小和小的区别

function getPosition( el ) {
    var x = 0;
    var y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
    x += el.offsetLeft - el.scrollLeft;
    y += el.offsetTop - el.scrollTop;
    el = el.offsetParent;
    }
    return { top: y, left: x };
}

查看示例坐标:http://javascript.info/tutorial/coordinates

评论

0赞 Jonathan Eunice 10/19/2016
不幸的是,这并不适用于现代 HTML 文档中可能找到的所有元素。例如,嵌入元素没有 、 和 属性。<svg>offsetLeftoffsetTopoffsetParent
0赞 KingRider 10/20/2016
它只是或,不是。查看“查看示例坐标”?你可以找到对象 svg 是位置调用 getOffsetRect,尝试并依赖对象工作。DIVIMGSVG
27赞 Alireza 5/22/2017 #21

像这样的东西怎么样,通过传递元素的 ID,它将返回左侧或顶部,我们也可以将它们组合起来:

1) 向左查找

function findLeft(element) {
  var rec = document.getElementById(element).getBoundingClientRect();
  return rec.left + window.scrollX;
} //call it like findLeft('#header');

2) 查找顶部

function findTop(element) {
  var rec = document.getElementById(element).getBoundingClientRect();
  return rec.top + window.scrollY;
} //call it like findTop('#header');

3) 同时找到左边和顶部

function findTopLeft(element) {
  var rec = document.getElementById(element).getBoundingClientRect();
  return {top: rec.top + window.scrollY, left: rec.left + window.scrollX};
} //call it like findTopLeft('#header');
6赞 MER 10/25/2017 #22

虽然这很可能在这么多答案的底部丢失,但这里的顶级解决方案对我不起作用。
据我所知,其他任何答案都无济于事。

情况
在 HTML5 页面中,我有一个菜单,它是标题中的导航元素(不是标题,而是另一个元素中的标题)。
我希望一旦用户滚动到导航,导航就会停留在顶部,但在此之前,标题是绝对定位的(所以我可以让它稍微覆盖其他东西)。
上面的解决方案从未触发更改,因为 .offsetTop 不会更改,因为这是一个绝对定位的元素。此外,.scrollTop 属性只是最顶层元素的顶部...也就是说,0 并且始终为 0。
我使用这两个执行的任何测试(与 getBoundingClientRect 结果相同)都不会告诉我导航栏的顶部是否曾经滚动到可查看页面的顶部(同样,正如控制台中报告的那样,它们在滚动时只是保持相同的数字发生)。

解决方案 对我来说,解决方案
是利用

window.visualViewport.pageTop

pageTop 属性的值反映了屏幕的可视部分,因此允许我跟踪元素相对于可视区域边界的位置。

可能不用说,每当我处理滚动时,我都希望使用此解决方案以编程方式响应正在滚动的元素的移动。
希望它能帮助别人。
重要提示:这似乎目前在Chrome和Opera中有效,绝对不适用于Firefox(6-2018)...在 Firefox 支持 visualViewport 之前,我建议不要使用这种方法,(我希望他们尽快这样做......它比其他的更有意义)。


更新:
只是关于此解决方案的说明。
虽然我仍然发现我发现的东西对于“......以编程方式响应正在滚动的元素的移动。对于我遇到的问题,更好的解决方案是使用 CSS 在元素上设置位置:粘性。使用 sticky,您可以在不使用 javascript 的情况下让元素保持在顶部(注意:有时这不会像将元素更改为固定元素那样有效,但对于大多数用途来说,粘性方法可能更胜一筹) UPDATE01:
所以我意识到,对于不同的页面,我有一个要求,

我需要在稍微复杂的滚动设置中检测元素的位置(视差加上滚动的元素past作为消息的一部分)。 我意识到,在那种情况下,以下内容提供了我用来确定何时做某事的值:

  let bodyElement = document.getElementsByTagName('body')[0];
  let elementToTrack = bodyElement.querySelector('.trackme');
  trackedObjPos = elementToTrack.getBoundingClientRect().top;
  if(trackedObjPos > 264)
  {
    bodyElement.style.cssText = '';
  }

希望这个答案现在更广泛地有用。

169赞 Mustkeem K 9/24/2018 #23

如果您只想在 javascript 中完成它,这里有一些使用 getBoundingClientRect()

window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y

window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X

第一行将返回相对于文档的 Y。 第二行将返回相对于文档的 X。offsetTopoffsetLeft

getBoundingClientRect() 是一个 javascript 函数,它返回元素相对于窗口视口的位置。

7赞 Kevin K. 3/1/2019 #24

要获得元素的总偏移量,您可以递归地汇总所有父偏移量:

function getParentOffset(el): number {
if (el.offsetParent) {
    return el.offsetParent.offsetTop + getParentOffset(el.offsetParent);
} else {
    return 0;
}
}

使用此实用函数,DOM 元素的总顶部偏移量为:

el.offsetTop + getParentOffset(el);
19赞 Văn Quyết 8/29/2019 #25

更新:

递归方法(在我的旧答案中)创建了许多调用堆栈。在这种情况下,我们可以使用 while 循环来避免递归:

/**
 *
 * @param {HTMLElement} el
 * @return {{top: number, left: number}}
 */
function getDocumentOffsetPosition(el) {
    let top = 0, left = 0;
    while (el !== null) {
        top += el.offsetTop;
        left += el.offsetLeft;
        el = el.offsetParent;
    }
    return {top, left};
}

旧答案:

/**
 *
 * @param {HTMLElement} el
 * @return {{top: number, left: number}}
 */
function getDocumentOffsetPosition(el) {
    var position = {
        top: el.offsetTop,
        left: el.offsetLeft
    };
    if (el.offsetParent) {
        var parentPosition = getDocumentOffsetPosition(el.offsetParent);
        position.top += parentPosition.top;
        position.left += parentPosition.left;
    }
    return position;
}

感谢 ThinkingStiff 的回答,这只是另一个版本。

1赞 Talha Rafique 7/18/2020 #26

这很容易,就像JS中的两行一样:

var elem = document.getElementById("id");    
alert(elem.getBoundingClientRect());

评论

4赞 mfluehr 12/2/2020
这个答案是不完整的,不会对以前的答案添加任何内容。
5赞 Azer8 5/24/2021 #27

    
HTML program to show (x, y) of an
element by dragging mouse over it  you just copied it and use it on your own 
<!DOCTYPE html>
<html>
    <head>
        <title>
            position of an element
        </title>
        
        <!-- scropt to get position -->
        <script type = "text/javascript">
            function getPositionXY(element) {
                var rect = element.getBoundingClientRect();
                document.getElementById('text').innerHTML
                = 'X: ' + rect.x + '<br>' + 'Y: ' + rect.y;
            }
        </script>
    </head>
    
    <body>
        <p>Move the mouse over the text</p>
        
        <div onmouseover = "getPositionXY(this)">
            Position:
            <p id = 'text'></p>
        </div>
    
    </body>
</html>                 

20赞 Philipp 8/16/2021 #28

下面是一个现代的 1 行代码,它使用 vanilla JS 递归地迭代 element.offsetTop 和 element.offsetParent

功能:

getTop = el => el.offsetTop + (el.offsetParent && getTop(el.offsetParent))

用法:

const el = document.querySelector('#div_id');
const elTop = getTop(el)

优势:

始终返回绝对垂直偏移量,而不考虑当前滚动位置。


传统语法:

function getTop(el) {
  return el.offsetTop + (el.offsetParent && getTop(el.offsetParent));
}

评论

0赞 n3wbsauce 10/7/2021
谢谢,找到 offsetParent 的 offsetTop 是帮助我找到正确位置的原因。
4赞 rahm_rny12 11/13/2022 #29

我可以喜欢或.例:element.offsetLeftelement.offsetTopdocument.getElementById('profileImg').offsetLeft

3赞 TheRanaEhtisham 3/2/2023 #30

这个简单示例检索表示简单元素的边界客户端矩形的 DOMRect 对象,并打印出其下方的属性。

更多说明

let elem = document.querySelector("div");
let rect = elem.getBoundingClientRect();
for (const key in rect) {
  if (typeof rect[key] !== "function") {
    let para = document.createElement("p");
    para.textContent = `${key} : ${rect[key]}`;
    document.body.appendChild(para);
  }
}
div {
  width: 400px;
  height: 200px;
  padding: 20px;
  margin: 50px auto;
  background: purple;
}
<div></div>