web-dev-qa-db-fra.com

Obtenir la position / le décalage de l'élément par rapport à un conteneur parent?

J'ai l'habitude de travailler avec jQuery. Cependant, dans mon projet actuel, j'utilise zepto.js. Zepto ne fournit pas de méthode position() comme jQuery. Zepto vient uniquement avec offset().

Une idée de comment je peux récupérer le décalage d'un conteneur par rapport à un parent avec js pur ou avec Zepto?

104
matt

Avertissement: jQuery, pas JavaScript standard

element.offsetLeft et element.offsetTop sont les propriétés JavaScript pures permettant de rechercher la position d'un élément par rapport à sa offsetParent; étant l'élément parent le plus proche avec une position de relative ou absolute

Alternativement, vous pouvez toujours utiliser Zepto pour obtenir la position d'un élément ET de son parent, et soustrayez simplement les deux:

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

Cela a l'avantage de vous donner le décalage d'un enfant par rapport à son parent même si le parent n'est pas positionné.

182
jackwanders

en js pur, utilisez simplement les propriétés offsetLeft et offsetTop.
Exemple de violon: 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>
48
fcalderan

Je l'ai fait comme ça dans 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;
};

=================== vous pouvez l'appeler comme ceci

getWindowRelativeOffset(top, inputElement);

Je me concentre sur IE uniquement selon mon objectif, mais des opérations similaires peuvent être effectuées pour d'autres navigateurs.

5
Imran Ansari

Ajoutez le décalage de l'événement au décalage de l'élément parent pour obtenir la position de décalage absolu de l'événement.

Un exemple :

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;

    }
}

Lorsque la cible de l'événement n'est pas l'élément auquel l'événement a été enregistré, elle ajoute le décalage du parent au décalage de l'événement en cours afin de calculer la valeur de décalage "Absolue".

Selon l’API Web Mozilla: "La propriété HTMLElement.offsetLeft en lecture seule renvoie le nombre de pixels correspondant au coin supérieur gauche de l’élément actuel décalé vers la gauche dans HTMLElement.offsetParent noeud. "

Cela se produit généralement lorsque vous avez enregistré un événement sur un parent contenant plusieurs enfants supplémentaires, par exemple: un bouton avec une icône interne ou une plage de texte, un élément li avec des plages internes. etc...

1
levi

J'ai une autre solution. Soustraire la valeur de la propriété parent de la valeur de la propriété enfant

$('child-div').offset().top - $('parent-div').offset().top;
1
Irshad Khan

Exemple

Donc, si nous avions un élément enfant avec un id "élément-enfant" et que nous voulions le positionner à gauche/en haut par rapport à un élément parent, disons une div ayant une classe de "élément-parent", utilisez ce code.

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

Plugin Enfin, pour le plugin actuel (avec quelques notes expliquant ce qui se passe):

// 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));

Note: Vous pouvez utiliser this sur un événement mouseClick ou mouseover

$(this).offsetRelative("div.item-parent");
1
Irshad Khan

C’est simple avec JS pur, faites-le simplement, travaillez pour les panneaux HTML 5 fixes et animés aussi, j’ai créé et essayé ce code, qui fonctionne pour tous les navigateurs (inclure 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>
0
Moises Conejo