160

我习惯于使用 jQuery。然而,在我当前的项目中,我使用 zepto.js。Zepto 没有提供position()像 jQuery 那样的方法。Zepto 仅附带offset().

知道如何使用纯 js 或 Zepto 检索容器相对于父级的偏移量吗?

4

7 回答 7

215

警告:jQuery,不是标准的 JavaScript

element.offsetLeft并且element.offsetTop是用于查找元素相对于其位置的纯 javascript 属性offsetParent;是最近的父元素,位置为relativeorabsolute

或者,您始终可以使用Zepto获取元素及其父元素的位置,然后将两者相减:

var childPos = obj.offset();
var parentPos = obj.parent().offset();
var childOffset = {
    top: childPos.top - parentPos.top,
    left: childPos.left - parentPos.left
}

这样做的好处是即使父级没有定位,也可以为您提供子级相对于其父级的偏移量。

于 2012-07-24T16:02:12.467 回答
104

在纯 js 中只需使用offsetLeftoffsetTop属性。
小提琴示例:http: //jsfiddle.net/WKZ8P/

var elm = document.querySelector('span');
console.log(elm.offsetLeft, elm.offsetTop);
p   { position:relative; left:10px; top:85px; border:1px solid blue; }
span{ position:relative; left:30px; top:35px; border:1px solid red; }
<p>
    <span>paragraph</span>
</p>

于 2012-07-24T16:02:46.227 回答
7

我在 Internet Explorer 中这样做了。

function getWindowRelativeOffset(parentWindow, elem) {
    var offset = {
        left : 0,
        top : 0
    };

    // relative to the target field's document
    offset.left = elem.getBoundingClientRect().left;
    offset.top = elem.getBoundingClientRect().top;

    // now we will calculate according to the current document, this current
    // document might be same as the document of target field or it may be
    // parent of the document of the target field
    var childWindow = elem.document.frames.window;
    while (childWindow != parentWindow) {
        offset.left = offset.left + childWindow.frameElement.getBoundingClientRect().left;
        offset.top = offset.top + childWindow.frameElement.getBoundingClientRect().top;
        childWindow = childWindow.parent;
    }

    return offset;
};

===================你可以这样称呼它

getWindowRelativeOffset(top, inputElement);

我只关注 IE,但其他浏览器也可以做类似的事情。

于 2013-10-08T08:15:16.103 回答
6

我得到了另一个解决方案。从子属性值中减去父属性值

$('child-div').offset().top - $('parent-div').offset().top;
于 2017-06-12T13:21:22.947 回答
2

将事件的偏移量加到父元素的偏移量上,得到事件的绝对偏移位置。

一个例子 :

HTMLElement.addEventListener('mousedown',function(e){

    var offsetX = e.offsetX;
    var offsetY = e.offsetY;

    if( e.target != this ){ // 'this' is our HTMLElement

        offsetX = e.target.offsetLeft + e.offsetX;
        offsetY = e.target.offsetTop + e.offsetY;

    }
}

当事件目标不是事件注册的元素时,它会将父级的偏移量与当前事件偏移量相加,以计算“绝对”偏移量值。

根据 Mozilla Web API:“ HTMLElement.offsetLeft只读属性返回当前元素的左上角在 HTMLElement.offsetParent 节点内向左偏移的像素数。

这通常发生在您在包含更多子项的父项上注册事件时,例如:具有内部图标或文本跨度的按钮,具有内部跨度的li元素。ETC...

于 2017-01-18T20:41:49.480 回答
2

例子

因此,如果我们有一个 id 为“child-element”的子元素,并且我们想获得它相对于父元素的左/上位置,比如一个具有“item-parent”类的 div,我们会使用此代码。

var position = $("#child-element").offsetRelative("div.item-parent");
alert('left: '+position.left+', top: '+position.top);

插件最后,对于实际的插件(用一些注释来解释发生了什么):

// offsetRelative (or, if you prefer, positionRelative)
(function($){
    $.fn.offsetRelative = function(top){
        var $this = $(this);
        var $parent = $this.offsetParent();
        var offset = $this.position();
        if(!top) return offset; // Didn't pass a 'top' element 
        else if($parent.get(0).tagName == "BODY") return offset; // Reached top of document
        else if($(top,$parent).length) return offset; // Parent element contains the 'top' element we want the offset to be relative to 
        else if($parent[0] == $(top)[0]) return offset; // Reached the 'top' element we want the offset to be relative to 
        else { // Get parent's relative offset
            var parent_offset = $parent.offsetRelative(top);
            offset.top += parent_offset.top;
            offset.left += parent_offset.left;
            return offset;
        }
    };

    $.fn.positionRelative = function(top){
        return $(this).offsetRelative(top);
    };
}(jQuery));

注意:您可以在 mouseClick 或 mouseover 事件上使用

$(this).offsetRelative("div.item-parent");
于 2017-06-12T07:34:29.567 回答
0

当然,使用纯 JS 很容易,只需这样做,也适用于固定和动画 HTML 5 面板,我制作并尝试了这段代码,它适用于任何浏览器(包括 IE 8):

<script type="text/javascript">
    function fGetCSSProperty(s, e) {
        try { return s.currentStyle ? s.currentStyle[e] : window.getComputedStyle(s)[e]; }
        catch (x) { return null; } 
    }
    function fGetOffSetParent(s) {
        var a = s.offsetParent || document.body;

        while (a && a.tagName && a != document.body && fGetCSSProperty(a, 'position') == 'static')
            a = a.offsetParent;
        return a;
    }
    function GetPosition(s) {
        var b = fGetOffSetParent(s);

        return { Left: (b.offsetLeft + s.offsetLeft), Top: (b.offsetTop + s.offsetTop) };
    }    
</script>
于 2017-03-29T22:17:17.487 回答