web-dev-qa-db-ja.com

offsetParentとparentElementまたはparentNodeの違い

私は次のDOM構造を持っています

<body>
    <div>
       <table>
          <outerElement>
              <innerElement />  
          </outerElement>
       <table>
    </div>
</body>

DIVのオーバーフローは自動に設定されているため、テーブルが大きくなると、DIV内でスクロールします。

このシナリオでは、なぜtable.offsetParentは、両方のtable.parentNodeparentElementはDivを返しますか?

ウィンドウ内のinnerElementの現在の位置を計算する必要があるので、そこからすべての親要素をトラバースして、offsetTopoffsetLeftの値を収集します。 DIV offsetParentが正常に機能するまでは、それを直接本体にスキップします。ある時点でスクロールが関係している場合の問題は、上記の例のDIVのように、scrollTopscrollLeftも考慮する必要があります。問題は、offsetParentを使用した場合、親の1つとしてDIVに遭遇したことがないことです。

[〜#〜]更新[〜#〜]

これは、トラバースを実行するコードの一部です。

while (oElem && getStyle(oElem, 'position') != 'absolute' && getStyle(oElem, 'position') != 'relative') { 
   curleft += oElem.offsetLeft;
   curtop += oElem.offsetTop;
   oElem = oElem.offsetParent;
}

ここで、getStyleは、この場合は位置スタイルを取得するカスタム関数です。

13
Yuriy Galanter

offsetParentに近づかないでください。正しく機能するように、多くのハックとチェックを追加する必要があります。

代わりに getBoundingClientRect を使用してみてください。

1
Ally

offsetParentは、position:relativeまたはposition:absoluteまたはページの本文を持つ最も近い親です。 parentNodeは、positionに関係なく、直接の親です。

36
kalley

GetBoudingClientRect()の使用は本当に大きな助けになります(ヒントをくれたAllyに感謝します!)。

それでもドキュメントの左上隅を基準にした位置が必要な場合は、次のスニペットが役立ちます。

_if (node.getBoundingClientRect) {
    var rect = node.getBoundingClientRect();
    var sx = -(window.scrollX ? window.scrollX : window.pageXOffset);
    var sy = -(window.scrollY ? window.scrollY : window.pageYOffset);

    return {
        x: rect.left - sx,
        y: rect.top - sy
    }
}
_

注:document.body.getBoundingClientRect()は、状況によってはFirefoxでtopに予期しない値を返す場合があります。したがって、ウィンドウのスクロール位置はより堅牢になります。

GetBoundingClientRect()をまだサポートしていないクライアントの場合でも、offetParentsをウォークし、すべての_overflow: scroll_(または自動)親が_position: relative_を持つように注意する必要があります。

4
BurninLeo