ブラウザーのビューポートを基準にして要素の上部の位置を取得するにはどうすればよいですか?


173

ブラウザーのビューポート(ページ全体ではなく、ページが表示されるビューポート)に対する要素の位置を取得したい。これはどのようにJavaScriptで実行できますか?

どうもありがとう


2
この質問は、stackoverflow.com / questions / 211703 / …に似ていると思います。
Jakob Runge 2013年

1
@JakobRunge、それは2013年に「いい」でしたか?
Iulian Onofrei 2017年

1
解決策を受け入れることを検討してください。
Iulian Onofrei 2017年

回答:


305

現在の回答は古くなっています。ネイティブgetBoundingClientRect()メソッドはかなり以前から存在しており、質問が要求することを正確に実行します。さらに、すべてのブラウザーでサポートされています(IE 5を含むようです!)

MDNページから:

戻り値はTextRectangleオブジェクトです。これには、境界線ボックスをピクセル単位で表す読み取り専用のleft、top、right、bottomプロパティが含まれ、左上がビューポートの左上を基準とします。

次のように使用します。

var viewportOffset = el.getBoundingClientRect();
// these are relative to the viewport, i.e. the window
var top = viewportOffset.top;
var left = viewportOffset.left;

3
これは、ブラウザズーム(Android Chrome)を使用すると正しく機能しない場合があります。この場合、@ rismからの解決策(以下を参照)が機能します
Dmitry

4
ほとんどの場合に適していますが、要素が埋め込みiframe内にないことを前提としています。問題は、ブラウザーのウィンドウの相対位置について尋ねることです。el.getBoundingClientRect()は、ブラウザウィンドウではなく、iframeのウィンドウに対して相対的に返します。
cakidnyc 2017年

6
問題は、ブラウザーのウィンドウの相対位置について尋ねることです。
Dmitry Dvornikov

2
@Denilson getBoundingClientRect().topは私のIE11にはありません。0を返します。解決策はありますか。
アリフ2018年

@アリフ:すみませんが、私はあなたの問題を再現できません。私は、IE11でこれをテストし、まだましな結果:codepen.io/denilsonsa/pen/ypqyXj
デニウソンSáマイア

57

私の場合、スクロールに関して安全を期すために、数式にwindow.scrollを追加しました。

var element = document.getElementById('myElement');
var topPos = element.getBoundingClientRect().top + window.scrollY;
var leftPos = element.getBoundingClientRect().left + window.scrollX;

これにより、スクロールされている場合でも、ドキュメント上の要素の実際の相対位置を取得できます。


2
スクロール位置を減算するのではなく、追加するのではないですか?
Iulian Onofrei 2017年

私は答えを賛成しましたが、それでも、@ lulianオノフライは正しいです。編集してください。
pmrotule 2017

@Fabio getBoundingClientRect().topは私のIE11にはありません。0を返します。解決策はありますか。
アリフ2018年

1
@Arif window.scrollY || window.pageYOffsetはサポートを改善する可能性があります
Fabian von Ellerts '

@FabianvonEllerts :)
Arif

15

編集: ページのスクロールに対応するコードを追加します。

function findPos(id) {
    var node = document.getElementById(id);     
    var curtop = 0;
    var curtopscroll = 0;
    if (node.offsetParent) {
        do {
            curtop += node.offsetTop;
            curtopscroll += node.offsetParent ? node.offsetParent.scrollTop : 0;
        } while (node = node.offsetParent);

        alert(curtop - curtopscroll);
    }
}

id引数は、オフセットが必要な要素のIDです。quirksmodeの投稿から転載


1
あなたの答えをありがとう、しかしあなたは私の質問を誤解していると思います、私はページに対して要素のトップを取得する方法を知っています、私がやろうとしていることは「ビューポート」(つまりブラウザウィンドウ)に対する相対的な位置を取得することです、ドキュメントではありません)
Waleed Eissa、2009

すみません、あなたの「ビューポート」の使用は私を投げました。それで、ブラウザのクロム、つまりブックマークツールバー、ロケーションバーなどを説明したいと言っているのですか?
Derek Swingley、2009

いいえ、ページが表示されるウィンドウのみです。ページがスクロールされる場合、これはドキュメントの上部とは異なり、それ以外の場合は同じです。
Waleed Eissa、2009

ああ、わかりました。それを行う方法がわからない...私が何かを思いついたら、私の答えを編集します。
Derek Swingley、2009

上記のコードを少し醜くしましたが、うまくいきます... offsetParent.scrollTopを使用してください
Derek Swingley 09

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

これは、ビューポートではなくドキュメントの上部から計算されているようです
Scott Leonard

6

あなたが試すことができます:

node.offsetTop - window.scrollY

Operaでビューポートメタタグを定義して動作します。


7
ドキュメントを正しく理解しいればoffsetTop、最も近い位置にある要素を基準にしています。これは、ページ構造に応じて、ルート要素である場合とそうでない場合があります。
DenilsonSáMaia 2017

5

jQueryはこれを非常にエレガントに実装します。jQueryののソースを見ると、offsetこれが基本的に実装方法であることがわかります。

var rect = elem.getBoundingClientRect();
var win = elem.ownerDocument.defaultView;

return {
    top: rect.top + win.pageYOffset,
    left: rect.left + win.pageXOffset
};

2

このページの関数は、ブラウザービューポートを基準にして、渡された要素の上、左、高さ、幅の座標を持つ長方形を返します。

    localToGlobal: function( _el ) {
       var target = _el,
       target_width = target.offsetWidth,
       target_height = target.offsetHeight,
       target_left = target.offsetLeft,
       target_top = target.offsetTop,
       gleft = 0,
       gtop = 0,
       rect = {};

       var moonwalk = function( _parent ) {
        if (!!_parent) {
            gleft += _parent.offsetLeft;
            gtop += _parent.offsetTop;
            moonwalk( _parent.offsetParent );
        } else {
            return rect = {
            top: target.offsetTop + gtop,
            left: target.offsetLeft + gleft,
            bottom: (target.offsetTop + gtop) + target_height,
            right: (target.offsetLeft + gleft) + target_width
            };
        }
    };
        moonwalk( target.offsetParent );
        return rect;
}

2
function inViewport(element) {
    let bounds = element.getBoundingClientRect();
    let viewWidth = document.documentElement.clientWidth;
    let viewHeight = document.documentElement.clientHeight;

    if (bounds['left'] < 0) return false;
    if (bounds['top'] < 0) return false;
    if (bounds['right'] > viewWidth) return false;
    if (bounds['bottom'] > viewHeight) return false;

    return true;
}

ソース


1

すべての回答をありがとう。Prototypeにはこれを行う関数(page()関数)がすでにあるようです。関数のソースコードを表示すると、最初にページ(つまり、ドキュメントの上部)に対する要素のオフセット位置が計算され、次にそこからscrollTopが減算されることがわかりました。詳細については、プロトタイプのソースコードを参照してください。


英断。ブラウザ間で同じ結果が得られる可能性が高いため、主要なライブラリのいずれかを使用するのがおそらく最善です。興味があれば、私の答えを確認してください。そこにあるコードはこれを実行しますが、ブラウザー間でどのように機能するかわかりません。
Derek Swingley、2009

1

idの要素がbtn1Webページに存在し、jQueryが含まれていると想定しています。これは、Chrome、FireFox、IE> = 9、およびEdgeのすべての最新ブラウザーで機能しました。jQueryは、ドキュメントに対する相対的な位置を決定するためにのみ使用されています。

var screenRelativeTop =  $("#btn1").offset().top - (window.scrollY || 
                                            window.pageYOffset || document.body.scrollTop);

var screenRelativeLeft =  $("#btn1").offset().left - (window.scrollX ||
                                           window.pageXOffset || document.body.scrollLeft);

1
jQueryはJavaScriptです。「100%バニラ/純粋なJSではない」
hungerstar

はい、そういう意味です。
サニル

1

getBoundingClientRect()オブジェクトのプロパティ値がIEで0を示す場合があります。その場合display = 'block'、要素を設定する必要があります。すべてのブラウザでオフセットを取得するには、以下のコードを使用できます。

jQuery機能を拡張します。

(function($) {
    jQuery.fn.weOffset = function () {
        var de = document.documentElement;
        $(this).css("display", "block");
        var box = $(this).get(0).getBoundingClientRect();
        var top = box.top + window.pageYOffset - de.clientTop;
        var left = box.left + window.pageXOffset - de.clientLeft;
        return { top: top, left: left };
    };
}(jQuery));

使用する :

var elementOffset = $("#" + elementId).weOffset();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.