2.

jQuery .width() / .height() 完全ガイド(innerWidth / outerWidth / 現代の代替)

編集
この記事の要点
  • .width() = content 部のピクセル値 (padding / border / margin 含まない)
  • .innerWidth() = content + padding
  • .outerWidth() = content + padding + border
  • .outerWidth(true) = content + padding + border + margin
  • window / document特殊扱いでビューポート / 文書全幅を返す
  • 現代の Vanilla JS では clientWidth / offsetWidth / getBoundingClientRect() / ResizeObserver

.width() / .height() の基本

// 取得(最初の要素の content 幅、px の数値)
$('#box').width();     // → 320
$('#box').height();    // → 200

// 設定(数値または文字列)
$('#box').width(500);
$('#box').width('50%');
$('#box').height('100vh');

// 関数で動的に
$('.box').width(function (i, currentWidth) {
    return currentWidth + 50;  // 各要素を 50px 拡げる
});

4 つのサイズ取得メソッド

jQuery にはサイズ取得が 4 種類あり、含まれる領域が異なります:

メソッド含まれる領域備考
.width()content純粋な中身
.innerWidth()content + padding境界線の内側
.outerWidth()content + padding + border境界線の外側
.outerWidth(true)content + padding + border + margin占有スペース全部

視覚的な比較:

要素のスタイル: width: 100px; padding: 10px; border: 5px solid; margin: 20px;

┌────── outerWidth(true) = 100+20+10+20+5+5 = 160 ──────┐
│  margin = 20                                          │
│  ┌──── outerWidth() = 100+20+10 = 130 ────┐           │
│  │border=5┌── innerWidth() = 100+20 = 120 ──┐         │
│  │        │padding=10                       │         │
│  │        │        ┌──width()=100──┐        │         │
│  │        │        │   content     │        │         │
│  │        │        └───────────────┘        │         │
│  │        │                                 │         │
│  │        └─────────────────────────────────┘         │
│  └──────────────────────────────────────────┘         │
└───────────────────────────────────────────────────────┘

box-sizing の影響

CSS の box-sizing プロパティで「width が何を指すか」が変わりますが、jQuery の .width() は常に content 部を返すので挙動が変わりません

/* デフォルト */
.box-a {
    box-sizing: content-box;
    width: 200px;        /* content = 200px */
    padding: 10px;
    border: 5px solid;
    /* 総幅 = 230px */
}

/* モダン CSS のデファクト */
.box-b {
    box-sizing: border-box;
    width: 200px;        /* content + padding + border = 200px */
    padding: 10px;
    border: 5px solid;
    /* 総幅 = 200px、content = 170px */
}
$('.box-a').width();        // 200 (content)
$('.box-a').outerWidth();   // 230 (content+padding+border)

$('.box-b').width();        // 170 (content) ← box-sizing 影響
$('.box-b').outerWidth();   // 200 (content+padding+border) ← CSS の width と一致

window と document の特殊扱い

// ビューポート(ブラウザ表示領域)
$(window).width();     // ビューポート幅
$(window).height();    // ビューポート高

// 文書全体(スクロール込み)
$(document).width();   // 文書幅
$(document).height();  // 文書高(コンテンツ含む)

// 用途別の使い分け
// レスポンシブ判定 → $(window).width()
// スクロール終端判定 → $(document).height() - $(window).scrollTop() - $(window).height()

Vanilla JS での代替

jQueryVanilla JS備考
$(el).width()el.clientWidth - paddingLeft - paddingRight純粋 content は計算必要
$(el).innerWidth()el.clientWidthcontent + padding
$(el).outerWidth()el.offsetWidthcontent + padding + border
$(el).outerWidth(true)offsetWidth + marginLeft + marginRightmargin は手動加算
$(window).width()window.innerWidthビューポート
$(document).height()document.documentElement.scrollHeight文書全体

getBoundingClientRect()

サブピクセルの小数値まで欲しい場合、またはtransform 後の見た目のサイズが欲しい場合:

const el = document.querySelector('#box');
const rect = el.getBoundingClientRect();

console.log(rect.width);   // 320.5 等の小数値
console.log(rect.height);  // 200.25 等
console.log(rect.top);     // ビューポート基準の Y
console.log(rect.left);    // ビューポート基準の X

// transform: scale(2) されていれば 2 倍の値が返る
// offsetWidth/clientWidth は transform 前の元サイズ

ResizeObserver: 要素サイズ変更を監視

$(window).resize() はウィンドウサイズ変更しか検知しません。個別要素のサイズ変更を検知するなら ResizeObserver:

const resizeObserver = new ResizeObserver((entries) => {
    for (const entry of entries) {
        const { width, height } = entry.contentRect;
        console.log(`サイズ変更: ${width} x ${height}`);
        // contentBoxSize / borderBoxSize も使える
    }
});

// 監視開始
resizeObserver.observe(document.querySelector('#card'));

// 停止
resizeObserver.disconnect();

レスポンシブ判定の実装例

// 旧 jQuery
$(window).on('resize', function () {
    if ($(window).width() < 768) {
        $('body').addClass('mobile');
    } else {
        $('body').removeClass('mobile');
    }
});

// 現代: matchMedia(再計算不要、軽量)
const mql = window.matchMedia('(max-width: 767px)');

function handleChange(e) {
    document.body.classList.toggle('mobile', e.matches);
}

mql.addEventListener('change', handleChange);
handleChange(mql);  // 初期実行

よくあるトラブル

症状原因対処
.width() が 0 を返す要素が display:none表示状態で取得、または getBoundingClientRect
画像のサイズが取れないload 前img.onload 待ち
iframe 内要素cross-origin同一オリジン化 or postMessage
transform 後のサイズが欲しいoffsetWidth は無視するgetBoundingClientRect
スクロールバーで横幅変動OS によって挙動差CSS scrollbar-gutter: stable

FAQ

Q: .width().css('width') どちらが推奨?
A: 数値計算するなら .width()(number)、文字列で扱うなら .css('width')("320px")。

Q: $(window).width()window.innerWidth の違い
A: ほぼ同じ。jQuery は OS 依存のスクロールバー考慮を一部行っていましたが、現代では window.innerWidth で十分。

Q: モバイルブラウザの 100vh が変
A: アドレスバーで変動する問題。100dvh(Dynamic Viewport Height)が CSS 2023 で標準化、Safari 15.4+ / Chrome 108+ で利用可。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. .css()
  2. .width()
  3. .height()
  4. .show()
  5. .ready()
  6. .attr()