jQueryで高さを取得・設定するメソッドは複数あり、何を取得するかによって使うメソッドが異なります。また、スマートフォンでは $(window).height() と CSS の 100vh がアドレスバーの影響で一致しないという実務でよくある問題があります。
この記事でわかること
- ブラウザ(ウィンドウ・ビューポート)の高さを取得する方法
- height() / innerHeight() / outerHeight() の違いと使い分け
- 取得した高さを要素に適用する基本パターン
- リサイズイベントへの対応(debounce最適化)
- スマホで100vhが正しく機能しない問題とCSS変数による解決策
ブラウザ(ウィンドウ・ビューポート)の高さを取得する
ブラウザの表示領域の高さを取得する方法は複数あります。それぞれ取得する値が微妙に異なります。
| メソッド/プロパティ | 取得できる値 | スクロールバー |
|---|---|---|
$(window).height() |
ビューポートの高さ(ブラウザの表示領域) | 含まない |
window.innerHeight |
ビューポートの高さ(スクロールバー含む) | 含む |
$(document).height() |
ページ全体の高さ(スクロール可能な全体) | — |
document.documentElement.clientHeight |
ビューポートの高さ(スクロールバー含まない) | 含まない |
// ビューポートの高さ(jQuery推奨)
var viewportH = $(window).height();
console.log('ビューポート高さ:', viewportH, 'px');
// ページ全体の高さ
var docH = $(document).height();
console.log('ページ全体の高さ:', docH, 'px');
// スクロール可能な最大量(ページ全体 - ビューポート)
var maxScroll = docH - viewportH;
console.log('最大スクロール量:', maxScroll, 'px');
$(window).height() はスクロールバー幅を除いた値
Windowsのブラウザではスクロールバーが常時表示されるため、
Windowsのブラウザではスクロールバーが常時表示されるため、
window.innerHeight と $(window).height() で数ピクセルの差が生じる場合があります。レイアウト計算には $(window).height() を使うのが安全です。要素の高さを取得する:height() / innerHeight() / outerHeight()
要素の高さを取得するメソッドも3種類あり、パディング・ボーダー・マージンを含むかどうかが異なります。
| メソッド | 含まれる範囲 | CSSのbox-modelとの対応 |
|---|---|---|
height() |
コンテンツ領域のみ | content-box |
innerHeight() |
コンテンツ + padding | padding-box |
outerHeight() |
コンテンツ + padding + border | border-box |
outerHeight(true) |
コンテンツ + padding + border + margin | margin-box |
var $box = $('#my-box');
console.log('height() :', $box.height(), 'px'); // コンテンツのみ
console.log('innerHeight() :', $box.innerHeight(), 'px'); // + padding
console.log('outerHeight() :', $box.outerHeight(), 'px'); // + padding + border
console.log('outerHeight(true):', $box.outerHeight(true),'px'); // + padding + border + margin
要素の高さ取得・設定の詳細は専用記事を参照
要素の幅・高さの取得と設定の詳細(width/height/css(“height”)の使い分けなど)は要素の幅・高さを取得・設定する完全ガイドを参照してください。
要素の幅・高さの取得と設定の詳細(width/height/css(“height”)の使い分けなど)は要素の幅・高さを取得・設定する完全ガイドを参照してください。
取得した高さを要素に適用する基本パターン
フルスクリーンのセクションやモーダルウィンドウなど、ブラウザの高さに合わせて要素サイズを動的に設定するパターンです。
単一要素への適用
$(function () {
// ビューポートの高さをそのまま要素に適用
$('#hero-section').css('height', $(window).height() + 'px');
});
複数要素への適用(ヘッダーを引いた残り高さ)
$(function () {
var headerH = $('#site-header').outerHeight(true);
var contentH = $(window).height() - headerH;
// コンテンツエリアをヘッダー以外の全高さに設定
$('#main-content').css('min-height', contentH + 'px');
});
height()で設定する vs css(“height”)で設定する
// どちらも同じ結果(数値で渡すとpx単位として処理される)
$('#box').height($(window).height()); // 数値のみ
$('#box').css('height', $(window).height()); // 単位なし数値もpxとして処理
$('#box').css('height', $(window).height() + 'px'); // 明示的にpx
// heightにパーセントや他の単位を使う場合は文字列で渡す
$('#box').css('height', '50vh');
リサイズイベントに対応する
ウィンドウサイズが変わるたびに高さを再計算・再設定するにはresize イベントを使います。resizeイベントは連続発火するためdebounceで最適化します。
function debounce(fn, wait) {
var timer;
return function () {
clearTimeout(timer);
timer = setTimeout(fn, wait);
};
}
function setFullHeight() {
var h = $(window).height();
$('#hero-section').css('height', h + 'px');
}
$(function () {
setFullHeight(); // 初期実行
// リサイズ時は200ms後に一度だけ実行(debounce)
$(window).on('resize', debounce(setFullHeight, 200));
});
スマートフォンでのスクロール中の高さ変化
iOSのSafariやChromeモバイルでは、スクロール中にアドレスバーが表示・非表示になり
iOSのSafariやChromeモバイルでは、スクロール中にアドレスバーが表示・非表示になり
$(window).height() の値が変化してresizeイベントが発火します。ページの高さが頻繁に変わると視覚的にがたつくため、後述のCSS変数を使った方法が推奨されます。スマホで100vhが正しく機能しない問題とCSS変数による解決策
スマートフォンのブラウザでは height: 100vh を指定すると、アドレスバーの高さを含んだ値になり、実際の表示領域からはみ出す問題があります。これはiOS Safari・モバイルChromeで広く知られた挙動です。
問題の仕組み
| 状況 | 100vhの値 | $(window).height()の値 |
|---|---|---|
| アドレスバーが表示されているとき | 画面全体の高さ(大きい) | アドレスバーを除いた高さ(小さい) |
| アドレスバーが非表示のとき(スクロール後) | 画面全体の高さ | 画面全体の高さ(一致) |
CSS変数(–vh)を使った解決策
JavaScriptで実際のビューポート高さを取得してCSS変数に設定し、CSSで var(--vh) を参照する方法が現在のベストプラクティスです。
function setVH() {
// window.innerHeightでより正確なビューポート高さを取得
var vh = window.innerHeight * 0.01;
// CSS変数としてルート要素に設定
document.documentElement.style.setProperty('--vh', vh + 'px');
}
$(function () {
setVH();
$(window).on('resize', debounce(setVH, 200));
});
CSS側での使い方
.hero {
/* 100vh の代わりに calc(var(--vh) * 100) を使う */
height: calc(var(--vh, 1vh) * 100);
}
/* フォールバック: --vh が未設定の場合は 1vh をデフォルト値として使用 */
.hero-section {
min-height: 100vh; /* 非対応環境向けフォールバック */
min-height: calc(var(--vh, 1vh) * 100);
}
CSS dvh(Dynamic Viewport Height)について
- CSS Level 4では
dvh(動的ビューポート高さ)が追加され、アドレスバーの変化に追従します - 2024年時点でChrome 108+・Safari 15.4+・Firefox 101+がサポート
height: 100dvhと書くだけで上記のCSS変数と同じ効果が得られます- IE11やサポートの古いブラウザが不要な場合は
dvhへの移行も検討できます
実務的な実装パターン:フルスクリーンヒーローセクション
ヘッダーを含む実際のページで、ヒーロー画像をビューポートいっぱいに表示する完全な実装例です。
<header id="site-header">ヘッダー</header> <section id="hero"> <h1>メインビジュアル</h1> </section> <main id="content">コンテンツ</main>
#hero {
background: #1e40af;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
/* JavaScriptでheightを上書きするため初期値はmin-height */
min-height: 100vh;
min-height: calc(var(--vh, 1vh) * 100);
}
function debounce(fn, wait) {
var timer;
return function () { clearTimeout(timer); timer = setTimeout(fn, wait); };
}
function adjustHero() {
// CSS変数を更新
var vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', vh + 'px');
// ヘッダーの高さを引いた残り高さをヒーローに設定
var headerH = $('#site-header').outerHeight();
var heroH = $(window).height() - headerH;
$('#hero').css('height', heroH + 'px');
}
$(function () {
adjustHero();
$(window).on('resize', debounce(adjustHero, 200));
});
まとめ
jQueryで高さを扱う際の要点は次の3点です。
- ウィンドウ高さは
$(window).height()、要素高さはpaddingやborderの含み方で使うメソッドが変わる - リサイズ対応はdebounceを使ってパフォーマンスを最適化する
- スマホの100vh問題はCSS変数
--vhまたはdvhで対応する
関連記事: 要素の幅・高さを取得・設定する完全ガイド / スクロールで要素が表示されたら実行する完全ガイド
よくある質問(FAQ)
Q$(window).height()とwindow.innerHeightの値が異なります。
AWindowsのブラウザでスクロールバーが表示されている場合、
window.innerHeight はスクロールバー幅を含んだ値になります。$(window).height() はスクロールバーを除いたコンテンツ領域の高さです。通常のレイアウト計算では $(window).height() を使ってください。スマホの100vh問題対応では window.innerHeight を使います。Qheight()とcss(“height”)の違いは何ですか?
A
height() は常に数値(ピクセル)を返します。css("height") はCSSに設定されている値を文字列で返します(例: "100px"、"auto"、"50%" など)。計算に使う場合は height() が便利です。height() で設定する場合は数値のみ、css("height") で設定する場合は単位付き文字列が必要です。Qdisplay:noneの要素の高さが0になります。
A
display:none の要素はDOMに存在しますがレンダリングされないため、height() は0を返します。正確な高さを取得するには、一時的に css({visibility:"hidden", display:"block"}) で不可視状態でレンダリングしてから高さを計測し、元の状態に戻す方法があります。QiPhoneでheight: 100vhがアドレスバーと重なってしまいます。
AこれはiOS SafariのCSSの仕様です。
100vh はアドレスバーを含んだ画面全体の高さを参照します。解決策は2つあります。①CSS変数 --vh をJavaScriptで設定して calc(var(--vh) * 100) を使う方法、②CSS4の 100dvh(Dynamic Viewport Height)を使う方法です。dvh はiOS 15.4以降のSafariでサポートされています。Qリサイズのたびに高さが変わってがたつきます。
Aスマートフォンでスクロール中にアドレスバーが出入りしてresizeイベントが発火しているためです。
window.innerHeight ではなく window.screen.height(物理画面高さ)を使う方法や、初回読み込み時の高さを変数に保存して以降は再計算しない方法もあります。またはCSSの dvh 単位を使うとJavaScriptなしで自動的に追従します。