スマートフォンのブラウザではスクロールするとアドレスバー等が自動で隠れるという動作が一般的ですが、これによってウィンドウの縦幅が変化することがあるので、それについて簡単にメモしておきます。
色々と調査できる余地があるのですが、いったん現時点でわかっていることを記録しておきます。後日加筆するかもしれません。
なお、マイナーバージョンや端末などの違いによって以下とは異なる結果になる可能性もあります。
1.ブラウザによってイベントが発生することもあればしないこともある
iOS(確認バージョンは8.3)のSafari、Android(確認バージョンは4.4.4。端末はSO-02G)の標準ブラウザ&Chromeでは、ページを下にスクロールしてアドレスバー等のナビゲーション表示が消えるときに resize イベントが発生しました。
ただし、上記3つのブラウザのうち、 Android の Chrome だけ、スクロール完了時(手を離し、慣性による移動も完了したあと)にイベントが発生しました。残りの2つは、スクロール中手を離していなくてもイベントが発生しました。これは、ブラウザのアドレスバー等が消えるタイミングの違いによるものだと思います。いずれも、アドレスバー等が消えた瞬間にイベントが発生するのは共通のようです。
一方、iOSのChromeでは resize イベントは発生しませんでした。
ちなみに、読み込み時に resize イベントが発生するかとか、画面回転時に resize イベントが発生するかとか、orientationchangeとどちらが先に実行されるのかとか、resizeイベントの発生タイミングについては、他にも色々と違いがあるようですが……このあたりは略します。
2.イベントは発生してもサイズが変化しているとは限らない?
まずiOSですが、Safari&Chromeで、jQuery を使って $(window).height() を取得すると、iOSのSafariではアドレスバー(あと下のナビゲーションバー)がある状態での表示領域(viewport: width=320pxの場合460px)が常に返ってきました。
つまり、アドレスバー等が非表示のときは、JavaScript で取得できるウィンドウ縦幅よりも実際に表示されているウィンドウ縦幅のほうが大きいことになります。へえ、そういうこともあるんですね……。ただし、縦幅を取得する方法はいくつかあるので、もしかしたら本当の縦幅を知る方法もあるかもしれません。
一方、Androidでは、標準ブラウザでもChromeでも、アドレスバー等の有無によって返ってくるウィンドウ縦幅が変化しました。
3.CSSでも同様
このウィンドウ縦幅に関する動作は JavaScript だけではなく、CSSでも同様のようです。具体的には、たとえばウィンドウ縦幅に要素の高さをあわせるというとき、方法として、よく知られているのが以下のやり方。
html, body, #hoge {
height: 100%;
}
<div id="hoge">高さをウィンドウ縦幅と同じにしたい要素</div>
このCSSにおける100%の基準は、上で書いた JavaScript で取得できるウィンドウ縦幅と同じになります。
重要なのが、Androidでは、100%がスクロールによって変化するということ。
たとえば「ファーストビュー全体にドーンと写真を載せたい」といったとき、PCやiOSなら上記の方法で特に問題ありませんが、Androidだとスクロール途中で高さが変わるので、アドレスバー等が消える瞬間に要素の縦幅が急に変わり、違和感のある動きとなってしまいます。
これに対応するひとつの解決策は、常にアドレスバー等が出るようにすることです。具体的には、skrollr のような JavaScript で擬似スクロールを行うライブラリを使用すれば、常にアドレスバー等が表示されるようにはなります。
しかしこの場合、表示領域が狭くなってしまうというデメリットもあります(パララックスっぽい効果を加えたいならスマートフォンでは上記のようなライブラリは必須なので、一石二鳥かもしれませんが……)。
何かスマートな解決法を募集中。