この記事では、3つのJavascript関数による高さの取得方法をまとめていきます。
とりわけ、モバイル環境における、ブラウザー(iOS Safari や Chrome)での高さの取得方法、ややトリッキーです。
詳しく見ていきます。
目次
Javacscript でブラウザーの高さを取得
ブラウザーのウィンドウに高さをフィットさせるには、下記の2種類のアプローチがあります。
- [A] Javascriptでウィンドウ高さを取得して、所望の要素を高さにぴったりフィットさせる
- [B] (Javascriptを使わずに)CSSでぴったりフィットさせる
今回、Javascript、もしくは、JQueryでの高さの方法を詳しく見ていきます。
ブラウザウィンドウの高さの取得
ブラウザーウィンドウの高さは、Javascript のdocumentオブジェクトのプロパティから、もしくは、jQueryを使って取得できます。
Javascriptの場合
// ブラウザーウィンドウの高さの取得
var windowHeight = document.documentElement.clientHeight;
jQuery の場合
// ブラウザーウィンドウの高さの取得 (上記と同値)
var windowHeight = $(window).height();
別の高さのプロパティもある・・?
一方で、多くの開発者は、Javascriptにおいては、ウィンドウ高さの取得には、「window.innerHeight」を先に思いつくはずです。
// ブラウザーウィンドウの高さ(アドレスバー・ツールバーを含むめたウィンドウ全体の高さ)
var windowHeight = window.innerHeight
どちらを使えばいいのでしょうか?もうすこし、この2つの「高さ」の定義の違いを深堀りしていきます。
それぞれの「高さ」の定義の違い
iOS Safari やChrome において、2つの高さの大きな違いは「静的な値か?動的な値か」という点です。
モバイルブラウザーでは、スクロール時にアドレスバーやツールバーが拡縮したり、隠れたりします。
document.clientElement.clientHeight は、ランディングした初期状態の値(アドレスバー大、ツールバーあり)をキープしますが、window.innerHeight は、動的に変化するのです。
「高さ」の定義がモバイルブラウザで微妙に違う!
注意が必要なのは、Firefox, Edge では、スクロール時にアドレスバー・ツールバーが拡縮したときの振る舞いが、Safari, Cromeと異なります。FireFox、Edge では、clientHeight の値も、スクロール時に変化してしまうのです。
スクロール時の描画エリアの変化に伴う、clientHeight / window.innerHeightの値
iOS ブラウザ (clientHeight / window.innerHeight)
- Safari: 変わらない / 変わる
- Chrome: 変わらない / 変わる
- Firefox: 変わる/変わる
- Edge: 変わる/変わる
Android ブラウザ (clientHeight / window.innerHeight)
- Chrome: 変わらない / 変わる
- Android ブラウザ: 変わらない /変わらない
- Firefox: (未テスト)
この違いは、例えば、ウィンドウのリサイズイベントで、ウィンドウサイズの変化してもぴったりあわせようとしたときに、影響します。
リサイズイベントで、高さを更新すると、FirefoxやEdge では、ページ内でスクロールするときに、ツールバーが出たり隠れたりすると、高さが変わってしまって、ページ全体がガタガタしてしまうのです。
これは厄介。またブラウザー問題に悩まされるのか〜。
ブラウザ高さ取得のテスト
ブラウザ高さの値の変化を、下のボタンからテストができます。ぜひお手元のモバイルブラウザーでお試しください。スクロール時、アドレスバーとツールバーの動きに合わせて、各種高さの値が変化するのがおわかり頂けると思います。
ピンク色のウィンドウがPCでは左上、モバイルではウィンドウ下部に表示されます。
後述のCSSの値もでていますので、読み進めながらテストしてみてくださいね。
ブラウザーのウィンドウ高さににフィットさせたいとき
さて、Javascriptで取得した高さをつかって、ブラウザーのCSSの content-box プロパティの値に注意しながら、対象の要素に高さを設定すれば、ウィンドウの高さにピッタリフィットさせることができます。
// ブラウザ高さを取得し
var windowHeight = document.documentElement.clientHeight;
// ターゲット要素の高さを合わせる (box-sizing: border-box)
$('.target-element').height(windowHeight)
// ターゲット要素が、box-sizing: content-box の場合はこちら
$('.target-element').outerHeight(windowHeight)
PCレイアウトでは、ユーザーがウィンドウ大きさをかえてしまうかもしれません。
ぴったりをキープするには、ウィンドウリサイズに追随させる必要があります。
var $target = $('.target-element');
// リサイズインベントで更新
$(window).resize(function() {
$target.height( document.documentElement.clientHeight );
});
この方法では、上記の通り、FireFox, Edge では、動的に値がかわってしまうので、注意してください。
PCのウィンドウ変化への追随を立てれば、モバイルFireFoxが犠牲になります。筆者はいったんシェアの低いFireFoxのガタガタ問題に目をつぶりました。迂回方法は色々とありそうですが、この記事ではフォローしないでおきます。
[参考]CSSをつかったピッタリフィット
Javascriptではありませんが、CSSをつかったフィット方法もご紹介。
CSS で一般的なのは viewport の高さ値を基準とする vh の利用です。モバイルブラウザーで注意が必要です。
// Viewport いっぱいにフィット
.target-element {
height: 100vh
}
問題はやはり、モバイルブラウザーのアドレスバー・ツールバーの高さです。
このvh は、アドレスバー・ツールバーを含む全体の高さを100%とするので、上記の指定では、ピッタリフィットしてもアドレスバーの高さだけ、ウィンドウからはみ出したり、ツールバーでかくされたりしてしまいます。
高さの値:height: fill-available を利用
このようなケースのために、特殊がSafariなど、一部のブラウザーで利用されています。比較的新しい記法です。
Google Chromeは、-webkit- のプレフィックスが必須です。(2021/5/1 v90.0 現在)
.target-element{
height: fill-element;
height: -webkit-fill-element;
}
他のブラウザーの対応状況も Can I Use: fill-available で確認しておきましょう。
ブラウザのシェアを考えれば、おおよそほとんどのケースで適応できると考えて良さそうですが、今の所、IE上で対応させる方法はないようです。
ベンダープリフィクスと、フォールバック値をひとまとめにしました。
elem {
height: 100vmax; /* IE用 フォールバック */
height: 100vh; /* フォールバック */
height: -moz-available;
height: -webkit-fill-available;
height: fill-available;
}
iOS や、Android デフォルトブラウザも、古いバージョンでは、動作しません。古いデバイスも出回っているので、フォールバック値を記載しておきましょう。
また、IE では「vh」も動作しませんので(Can I Use: vw, vh)、 vmax を利用する必要があります。
上記の 100vh , 100vmax のフォールバックはブラウザの高さにぴったりフィットはしませんが、だいたい似たようなレイアウトを保証します。(他の固定値でもかまいません。)
おまけ:その他のCSSでの方法
おまけで、別のCSS方法も紹介します。
<html>
<body>
<div class="target-element"></div>
</body>
</html>
html, body{
height:100%
}
.target-element{
height:100%
}
このhtml 要素100%の値は、Javascript の「document.documentElement.clientHeight」と同じ値です。(iOS Safari, Chromeでのみ確認)
一方で、CSSの基本仕様で「height: 100%」は親要素の高さが名言されている場合のみ有効ですので、この記法が利用できるケースはかなり限定されます。
結局、どの方法が良いか?
クロスブラウザで、間違いなく適応させたいのであれば、Javascript を使った方法が間違いないでしょう。実装も複雑ではなく、動的な追随をどうするかに関しても迂回方法の自由度が高いですので、筆者からはおすすめです。
何らかの理由でどうしてもJavascriptを避けたいのであれば、CSS height を、fill-available をベンダープリフィックスとともに使うのが良いでしょう。フォールバックをお忘れなく。
参考文献:
- document.documentElement.clientHeight:
- (px)
- $(window).height():
- (px)
- window.innerHeight:
- (px)
- CSS vh:
- (px)
- CSS fill-available:
- (px)
Javascript で取得するブラウザ高さの値を、徹底解剖じゃ!