jQuery でサイズや位置を取得する方法を図にしてみた

更新履歴

2010-01-21
本エントリの内容も含めた最新の情報は下記エントリをご参照ください。

サイズの取得

煩雑になるので height の記述しかありませんが、width に置き換えれば幅もとれます。

普通のボックス要素

height() メソッドで取得できる値には、padding や border の分の高さを含みません。
CSS の height と同じなので、css('height')メソッドで取得してもよさそうですが、こちらの場合ブラウザの種類や CSS の定義の仕方で取得される値が異なる(クロスブラウザとしての機能が完全でない)ので、純粋に px 単位の高さを取得したい場合は height() メソッドを使用した方が無難です。

スクロールバー付きボックス要素

clientHeight には スクロールバーの高さは含まれません。

自分もよくやるのですが、スクロールバーの高さや幅をリテラルで 16px として処理してる jQueryプラグインなどを見かける時があります。
デスクトップのカスタマイズ系ソフトで、スクロールバーの幅や高さを変更できるものを見かけた記憶がありますが、そういった場合 16px 固定による処理は問題がありそうです。

試しに以下ロジックでスクロールバーの高さが算出できるか試してみました。

$j.fn.cssNum = function(attr){
    try{
        parseInt(this.css(attr))||0;
    }
    catch(e){
        return 0;
    }
}
$j.fn.scrollbarHeight = function(){
    return this.attr('offsetHeight')
           - this.cssNum('border-top-width')
           - this.cssNum('border-bottom-width')
           - this.attr('clientHeight');
}
IE6,7 17px
Opera9.5 17px
Firefox3 17px
Safari 15px

それっぽい値は取れますが 16px は1つもないですね。
ちなみに html 要素では上記の計算式の理屈が当てはまらないので使えません。


scrollHeight はスクロールできない状態(内包要素が自領域からはみ出てない状態)の場合は、clientHeight と同じ値になりますが、IE の場合のみ内包要素の高さと同じ値になってしまいます。

下記のように2つの値を比較し、大きい方の値を scrollHeight とした方が良さそうです。

$j.fn.scrollHeight=function(){
    var ch=this.attr('clientHeight');
    var sh=this.attr('scrollHeight');
    return $j.browser.msie && ch>sh?ch:sh;
}
非表示領域を持つスクロールバー付きボックス要素

scrollHeight で非表示領域の部分も含めた全体の大きさが取得できます。
内包要素全体をレイヤーで覆いたい時などに使えそうです。

位置の取得

scrollTop , scrollLeft メソッド

スクロール量を取得できます。先の clientHeight や clientWidth を併用すれば、特定の要素が表示領域内にあるかどうかなどの判定処理にも使えます。

offset メソッド

図のように各要素の絶対位置を返してくれます。前回のエントリでも少し触れましたが、親・先祖要素の position:relative,absolute の有無や border や margin も計算の上で絶対位置を返してくれるのですごく便利です。
ちなみに CSS 的な意味での位置、つまり position:relative や absolute な要素からの相対位置が欲しい場合は、css() メソッドで取得できますが、CSS 側での指定の仕方によりブラウザ毎に異なる値の取れ方をします。(先ほどのサイズ取得と同じ問題。得に Firefoxがひどい)
ですので、プラグインのように様々な指定のされ方を想定した処理の中で CSS 的な位置が欲しい場合は、自身の offset() メソッドの取得値と、relative , absolute な直近の親・先祖要素の offset() メソッドの取得値の差分で求めた方が確実です。

2008.12.26 追記
position() メソッドで簡単に取得できるようです。詳しくはこちら