旧ブログ(ISSEN)から移行しました

スマホで100vhが画面高さいっぱいにならない時の対処法

スマホで100vhが画面高さいっぱいにならない時の対処法

成岡拓哉
成岡拓哉5分で読めます

はじめに

こんにちは!株式会社TOKOSのエンジニアのタクヤです!
今回は、スマホで100vhが画面高さいっぱいにならない時の対処法をご紹介します。

今回は下記2つの方法をご紹介します。

dvhを使う
②カスタムプロパティ + JavaScriptを使う

プロジェクトに合わせて使い分けてください!

環境

動作確認環境はiOS Safariバージョン16.5です。
リセットCSSを使用しています。

normalize.css/normalize.css at master · necolas/normalize.css

A modern alternative to CSS resets. Contribute to necolas/normalize.css development by creating an account on GitHub.

github.com

環境によっては多少スタイルが崩れる可能性があるため、十分に注意が必要です。

vh, dvhについて

画面高さいっぱいを100vhで実装した時の問題

画面の高さいっぱいのメインビジュアルなどの要素を作る時、height: 100vhを指定していませんか?
そうすると、PCでは問題ないのにスマホでは高さが合わず上手くいきません。

原因は、スマホだとツールバーやアドレスバーといった動的バーが存在するため、画面高さが常に一定ではないからです。

100vhについて

画面高さいっぱいを実現する時、height: 100vhをよく使いますが、その100vhは画面いっぱいの高さではなく、厳密には動的バーが表示されていない時の高さです。

そのため、動的バーが表示されている時(ページを上方向にスクロールした時など)には画面高さいっぱいになっていないのです。

その他のvhについて

私も最近まで知らなかったのですが、vhには他に似たようなモノが存在します。

  • svh
    動的バーが表示されている状態の画面高さの1%
  • lvh
    動的バーが表示されていない状態の画面高さの1%
  • dvh
    動的バーの表示非表示を考慮した画面高さの1%
    簡単に言うと、svhlvhを出し分けてくれるものです。

これら以外にもあるそうですが今回の説明は3つまでにします。
(画面横方向のvwも同じようにあります。)

dvhを使えば常に画面高さいっぱいを実現できそうです。

実装

dvhで実装してみる

dvhを使用してスマホで画面高さいっぱいを実装する方法を、vhの場合と併せて説明します。

HTML
<div class="spacer"></div>
<!-- 100vhを指定する要素 -->
<div class="box --vh">
  <div class="item --top">90%</div>
  <div class="item --bottom">10%</div>
</div>
<div class="spacer"></div>
<!-- 100dvhを指定する要素 -->
<div class="box --dvh">
  <div class="item --top">90%</div>
  <div class="item --bottom">10%</div>
</div>
CSS
.box {
  color: #fff;
  font-size: 32px;
}
 
/* 100vhを指定する要素 */
.box.--vh {
  align-items: center;
  height: 100vh;
}
 
/* 100dvhを指定する要素 */
.box.--dvh {
  height: 100dvh;
}
 
.item {
  align-items: center;
  display: flex;
  justify-content: center;
}
 
.item.--top {
  background-color: #34d276;
  height: 90%;
}
 
.item.--bottom {
  background-color: #2cb5b9;
  height: 10%;
}
 
.spacer {
  background-color: #e4e4e4;
  height: 500px;
}

100vhの場合

100vhの場合、動的バーが表示されていると高さいっぱいになってくれていないことがわかります。

100dvhの場合

反対に、100dvhの場合だと動的バーが表示されていても高さいっぱいになってくれています。

dvhを使えば簡単に実装できましたね!
ですが、dvhにも大きな問題点があります。。。

対応しているブラウザが少ない

なんとdvhですが、対応しているブラウザが全くもって少ないです。
iOS safariの場合16.4以降のみ対応のため、実用レベルになるまで少し時間がかかりそうです。

カスタムプロパティ + JavaScriptを使う

dvhはまだ実用レベルではないため、別の方法をご紹介します。
CSSのカスタムプロパティとJavascriptを使用する方法です。

index.html
<div class="spacer"></div>
<!-- カスタムプロパティ + JavaScript -->
<div id="custom" class="box --custom">
  <div class="item --top">90%</div>
  <div class="item --bottom">10%</div>
</div>
<div class="spacer"></div>
style.css
.box {
  color: #fff;
  font-size: 32px;
}
 
/* カスタムプロパティ + JavaScript */
.box.--custom {
  height: 100vh; /* フォールバック */
  height: calc(var(--custom, 1vh) * 100);
}
 
.item {
  align-items: center;
  display: flex;
  justify-content: center;
}
 
.item.--top {
  background-color: #34d276;
  height: 90%;
}
 
.item.--bottom {
  background-color: #2cb5b9;
  height: 10%;
}
 
.spacer {
  background-color: #e4e4e4;
  height: 500px;
}
app.js
const setCustomHeight = () => {
  const customVhElement = document.getElementById("custom") // 対象の要素を取得
  const customVh = window.innerHeight * 0.01 // 画面高さを取得
  customVhElement.style.setProperty("--custom", `${customVh}px`) // カスタムプロパティに値を入れる
}
 
// 画面にリサイズがあった時に処理を実行
window.addEventListener("resize", setCustomHeight)
 
// 処理の初期実行
setCustomHeight()

画面がリサイズされる度に関数を呼んでいます。
その関数は、画面高さを計算し、--customというカスタムプロパティに対してその計算した値を入れてくれます。
これで、動的バーが表示されても要素の高さがそれに応じて変化してくれるため、画面高さいっぱいが実現できます。

ブラウザやデバイスの差異を気にする必要はありません。

さいごに

今回は、スマホで100vhが画面高さいっぱいにならない時の対処法について紹介しました。
①dvhを使う方法と、②カスタムプロパティ + JavaScriptを使うの2種類の方法をご紹介しました。
①は現時点では使えるブラウザが限られているため、②の方法を使うのが良いですね!

今回の内容にもあった、viewportや高さ関わるCSSについて詳しく記載されています!
ぜひ読んでみてください!

Amazon

Amazon

www.amazon.co.jp

この記事を書いた人

成岡拓哉
成岡拓哉

TOKOSのフロントエンドエンジニア。企業サイトやLPの制作を担当しています。このブログではWeb制作初学者向けに、実務で役立つ知識を分かりやすく発信しています。ビールが好きです🍺