CSSの新しいViewport単位「dvh」とは?vhやlvh/svhとの違い、モバイル時代のレイアウト課題と解決策を徹底解説
はじめに:モバイル時代のViewportとCSSの挑戦
現代のウェブデザインは、モバイルデバイスへの対応が不可欠です。スマートフォンやタブレットでウェブサイトを閲覧するユーザーは年々増加しており、デスクトップと同じように快適で美しい体験を提供することが求められています。レスポンシブデザインはもはや特別な技術ではなく、標準的な開発手法となりました。
レスポンシブデザインの根幹をなす要素の一つに、CSSのViewport単位があります。Viewportとは、ブラウザの表示領域のことです。CSSでは、このViewportのサイズを基準にした相対的な単位として、古くからvw
(Viewport Width)とvh
(Viewport Height)が利用されてきました。これらの単位は、要素のサイズや余白を画面サイズに応じて柔軟に変化させるのに非常に強力なツールです。
しかし、特にモバイル環境において、従来のvh
単位には長年の課題がありました。それは、ブラウザのユーザーインターフェース(UI)、具体的にはアドレスバーやツールバーといった要素が、ユーザーのスクロール操作によって表示されたり隠れたりする挙動に起因するものです。この動的なUIの表示/非表示が、vh
で定義された要素の高さに予期しない影響を与え、レイアウトの崩れや不自然な余白を生じさせる原因となっていました。
この問題を解決するために、CSSの新しいViewport単位群が標準化されました。それが、svh
(Small Viewport Height)、lvh
(Large Viewport Height)、そして本記事の主役であるdvh
(Dynamic Viewport Height)です。これらの新しい単位は、モバイルブラウザの動的なUIを考慮に入れ、開発者がより意図した通りのレイアウトを実現できるように設計されています。
本記事では、まず従来のvh
単位の基本的な使い方と、モバイル環境での課題を詳しく説明します。次に、新しい単位であるsvh
、lvh
、dvh
それぞれの定義、挙動、メリット、デメリットを掘り下げて解説します。そして、これらの単位を比較し、どのようなケースでどの単位を選ぶべきか、具体的な使い分けの指針を示します。さらに、実践的なコード例、ブラウザサポート状況、実装上の注意点についても詳しく解説します。
本記事を読むことで、あなたはCSSの新しいViewport単位を深く理解し、現代のモバイルフレンドリーなウェブサイト開発において、より堅牢で柔軟なレイアウトを構築するための知識とツールを手に入れることができるでしょう。さあ、新しいViewport単位の世界へ一緒に踏み込みましょう。
従来のViewport単位:vw
とvh
の基礎と限界
まず、新しい単位が登場する以前から存在する、基本的なViewport単位であるvw
とvh
について復習しておきましょう。
vw
(Viewport Width): Viewportの幅の1%を表す単位です。vh
(Viewport Height): Viewportの高さの1%を表す単位です。
例えば、画面幅が1000px、画面高さが800pxの場合、
* 1vw
は10px
* 1vh
は8px
となります。
要素のサイズや余白をこれらの単位で指定すると、Viewportのサイズが変わるのに合わせて要素のサイズも相対的に変化します。これにより、異なる画面サイズのデバイスで、要素の大きさや配置のバランスを維持したまま表示させることができます。これがレスポンシブデザインの基本的な考え方の一つです。
vw
とvh
の基本的な使用例
“`css
.full-width {
width: 100vw; / Viewportの幅いっぱいに広がる /
}
.full-height-section {
height: 100vh; / Viewportの高さいっぱいに広がる /
}
.responsive-text {
font-size: 5vw; / Viewportの幅に応じてフォントサイズが変わる /
}
.padding-around {
padding: 2vh 3vw; / Viewportの高さと幅に応じて余白が変わる /
}
“`
デスクトップ環境では、ブラウザのウィンドウサイズを変更しない限り、Viewportの幅と高さは基本的に一定です。そのため、vw
やvh
で指定された要素のサイズは固定され、予測通りのレイアウトが得られます。特にheight: 100vh;
は、ヒーローセクション(ウェブサイトのファーストビューに表示される、画面いっぱいの大きなセクション)を作る際によく使われるテクニックでした。これにより、ユーザーがページを開いた瞬間に、画面全体にコンテンツを表示させることができます。
vh
がモバイル環境で抱える問題:「動的ツールバー問題」
デスクトップではうまく機能するvh
単位ですが、モバイル環境では問題が生じます。これは、モバイルブラウザのViewportの「高さ」が、デスクトップのように常に一定ではないことに起因します。
スマートフォンでウェブサイトを閲覧しているとき、ページをスクロールするとブラウザのアドレスバーや下部のナビゲーションツールバーが自動的に隠れることがあります。これは、より広い画面領域をコンテンツ表示のために解放し、ユーザー体験を向上させるための機能です。逆に、ページを一番上までスクロールしたり、下にスクロールしている途中で上方向に少しスクロールしたりすると、これらのツールバーが再び表示されます。
このツールバーの表示/非表示によって、ブラウザの「見た目の」表示領域の高さは変化します。しかし、従来のvh
単位は、この動的な変化を考慮していませんでした。多くのモバイルブラウザでは、vh
は「ツールバーが常に表示されている状態でのViewportの高さ」を基準に計算されていました。これは、Viewportの「論理的な」最大サイズ、あるいは初期表示サイズに基づいているとも言えます。
この問題の具体的なシナリオ:
- ユーザーがモバイルデバイスでページを開きます。ブラウザのツールバーが表示されています。
height: 100vh;
と指定された要素は、ツールバーが表示された状態でのViewportの高さ(例: 600px)の100%、つまり600pxの高さで表示されます。要素は画面いっぱいに見えます。- ユーザーがページを少し下にスクロールします。ブラウザのツールバーが非表示になり、Viewportの実際の表示領域の高さが増加します(例: 650px)。
- しかし、
height: 100vh;
で指定された要素の高さは、ツールバーが表示されていた時の基準(600px)から変化しません。 - 結果として、ツールバーが非表示になった後、要素の高さ(600px)は現在のViewportの実際の高さ(650px)よりも小さくなり、要素の下部に50pxの不要な余白ができてしまいます。
この「要素の下部に余白ができる」問題は、特にheight: 100vh;
を使ってヒーローセクションや全画面表示の要素を実装した場合に顕著になります。スクロールするたびに画面下部のレイアウトがずれて見えるという、ユーザー体験を損なう要因となっていました。
逆に、一部のブラウザや特定の状況下では、vh
が「ツールバーが隠れて最大の高さになった状態」を基準に計算されることもあり、その場合はツールバーが表示された際に要素の一部が画面外に押し出されてしまうという問題も発生しました。ブラウザの実装によって挙動が異なることも、開発者にとっては頭痛の種でした。
このようなモバイルブラウザ特有の「動的なUIによるViewport高さの変化」と、従来のvh
単位がその変化に対応できない問題が、「動的ツールバー問題」として知られるようになり、より予測可能で柔軟なレイアウトを実現するための新しいCSS単位の必要性が高まったのです。
新しいViewport単位:svh
, lvh
, dvh
の登場
「動的ツールバー問題」に対処するため、CSS仕様ではViewportの新しい単位群が導入されました。これらは、Viewportの高さ(および幅)を、ブラウザUIの状態に応じて異なる基準で定義することで、開発者が意図した挙動を選択できるように設計されています。
新しい単位は以下の通りです。
- Small Viewport単位 (
svw
,svh
): ブラウザの動的UI要素(ツールバーなど)が常に表示されている状態でのViewportサイズを基準とします。これは、Viewportの「最小」の可能なサイズです。 - Large Viewport単位 (
lvw
,lvh
): ブラウザの動的UI要素が非表示になっている状態でのViewportサイズを基準とします。これは、Viewportの「最大」の可能なサイズです。 - Dynamic Viewport単位 (
dvw
,dvh
): ブラウザの動的UI要素の表示状態に関わらず、現在のViewportの実際のサイズを基準とします。これは、UIの表示/非表示に応じて動的に変化します。
これらの単位は、CSS Values and Units Module Level 4仕様の一部として標準化されました。これにより、ブラウザ間の互換性が向上し、開発者はモバイル固有のViewport問題に対して、より標準的かつ強力な解決策を利用できるようになりました。
ここからは、本記事の主要テーマである高さの単位に焦点を当て、svh
, lvh
, dvh
それぞれを詳しく見ていきましょう。
svh
(Small Viewport Height) の詳細
svh
は「Small Viewport Height」の略で、ブラウザの動的ツールバー(アドレスバー、ナビゲーションバーなど)がすべて表示されている状態におけるViewportの高さの1%を表します。これは、Viewportが取りうる「最小」の高さです。
つまり、100svh
と指定された要素は、モバイルブラウザでページを開いた直後や、ツールバーが表示されている状態でのViewportの高さと正確に一致します。
svh
の挙動と特徴
- 高さが固定される:
svh
で定義された要素の高さは、ツールバーの表示/非表示に関わらず、Small Viewport(ツールバー表示時)の高さに基づいて固定されます。スクロール操作によってツールバーが隠れても、要素自体の高さは変化しません。 - 予測可能なレイアウト: ツールバーが表示されている状態での高さに固定されるため、レイアウトが予測しやすく安定します。要素が画面外に押し出される心配がありません。
svh
の使用例
“`css
/ ツールバーが表示されていても画面内に収まるヒーローセクション /
.hero-section-svh {
height: 100svh;
background-color: lightblue;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 2em;
text-align: center;
}
/ 固定ヘッダーとフッターがある場合のメインコンテンツ領域 /
header { height: 60px; background-color: #f0f0f0; }
footer { height: 50px; background-color: #e0e0e0; }
.main-content-svh {
/ Viewportの最小高さからヘッダーとフッターの高さを引く /
min-height: calc(100svh – 60px – 50px);
background-color: lightgreen;
padding: 20px;
}
“`
svh
のメリット
- レイアウトの安定性: ツールバーが表示された状態を基準とするため、要素が画面下部に隠れてしまうリスクがありません。特に、常にユーザーの視界に収まっていてほしい要素(例: ページ全体のコンテナ、特定のUI要素)に対して、予測可能な高さを確保できます。
- 「動的ツールバー問題」の下部隠れを防ぐ: 従来の
vh
がもし最大高さを基準に計算されていた場合、ツールバー表示時に要素が画面外に押し出されることがありましたが、svh
はこれを防ぎます。
svh
のデメリット
- 余白の発生: ツールバーが非表示になり、Viewportの実際の高さがSmall Viewportの高さよりも大きくなった場合、
100svh
の要素は現在の画面高さに対して小さくなるため、要素の下部に余白ができてしまいます。これが、従来のvh
で多くの開発者が遭遇した問題と全く同じ見た目の結果になることがあります。 - 画面領域の最大限の活用が難しい: ツールバー非表示時の広い画面領域を要素の高さとして最大限に活用することはできません。
svh
はどんな時に使うべきか?
- 要素がツールバーと重なって画面外に隠れてしまうことを絶対に避けたい場合。
- 固定ヘッダーやフッターがあり、その間のコンテンツ領域がツールバー表示時でも確実に表示されるようにしたい場合。
- レイアウトの安定性、予測可能性を最も重視する場合。
svh
は、従来のvh
が多くのブラウザで(意図せずとも結果的に)採用していた挙動に最も近い単位と言えます。動的な高さ変化による予期せぬレイアウト崩れを防ぐという点では有効ですが、ツールバー非表示時に余白ができてしまうという従来の課題は引き継ぎます。
lvh
(Large Viewport Height) の詳細
lvh
は「Large Viewport Height」の略で、ブラウザの動的ツールバーがすべて非表示になっている状態におけるViewportの高さの1%を表します。これは、Viewportが取りうる「最大」の高さです。
つまり、100lvh
と指定された要素は、モバイルブラウザでツールバーが非表示になっている状態でのViewportの高さと正確に一致します。
lvh
の挙動と特徴
- 高さが固定される:
lvh
で定義された要素の高さは、ツールバーの表示/非表示に関わらず、Large Viewport(ツールバー非表示時)の高さに基づいて固定されます。スクロール操作によってツールバーが表示されても、要素自体の高さは変化しません。 - 画面領域の最大活用: ツールバーが非表示になっている時の最も広い画面領域を基準とするため、その状態では画面いっぱいに要素を表示できます。
lvh
の使用例
“`css
/ ツールバー非表示時に画面いっぱいに広がるヒーローセクション /
.hero-section-lvh {
height: 100lvh;
background-color: coral;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 2em;
text-align: center;
}
/ 全画面表示のモーダルやオーバーレイ /
.modal-overlay-lvh {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100lvh; / ツールバー非表示時の最大高さを利用 /
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
}
“`
lvh
のメリット
- 画面領域の最大限の活用: ツールバー非表示時の広い画面領域を有効活用できます。ヒーローセクションや全画面表示の要素など、没入感を重視するデザインに適しています。
- 「動的ツールバー問題」の余白発生を防ぐ: ツールバーが非表示になった時に要素の下部に余白ができてしまう問題を回避できます。
lvh
のデメリット
- 要素の隠れ: ツールバーが表示され、Viewportの実際の高さがLarge Viewportの高さよりも小さくなった場合、
100lvh
の要素は現在の画面高さよりも大きくなるため、要素の下部がツールバーの後ろに隠れてしまう可能性があります。これは、ユーザーがコンテンツの一部を見失うことにつながり、UXを損なう可能性があります。 - レイアウト崩れのリスク: 要素の一部が隠れることで、意図しないレイアウト崩れや、スクロールが必要になるなどの問題が発生する可能性があります。
lvh
はどんな時に使うべきか?
- 全画面表示の要素(ヒーローセクション、スプラッシュスクリーン、全画面モーダルなど)で、画面領域を最大限に活用し、没入感を出したい場合。
- ツールバーが表示された際に要素の下部が隠れても許容できる、あるいは隠れても問題ないデザインである場合。
- ツールバー非表示時の余白発生を確実に避けたい場合。
lvh
は、ツールバー非表示時の広々とした画面を活かしたい場合に強力な選択肢となりますが、ツールバー表示時のレイアウト崩れのリスクを理解しておく必要があります。
dvh
(Dynamic Viewport Height) の詳細
dvh
は「Dynamic Viewport Height」の略で、ブラウザの動的ツールバーの表示状態に関わらず、その瞬間のViewportの実際の高さの1%を表します。これは、ブラウザのUIの表示/非表示に応じて、その値が動的に変化する単位です。
つまり、100dvh
と指定された要素の高さは、ツールバーが表示されている時はSmall Viewportの高さに、ツールバーが非表示の時はLarge Viewportの高さに、そしてその中間状態ではそれに応じた高さに変化します。
dvh
の挙動と特徴
- 高さが動的に変化する:
dvh
で定義された要素の高さは、ユーザーのスクロール操作によってブラウザツールバーが表示されたり隠れたりするのに合わせて、シームレスに変化します。 - 常に現在の表示領域にフィット: 要素の高さは常に、その瞬間のViewportの実際の表示可能な領域の高さと一致します。
dvh
の使用例
“`css
/ 常に現在のViewportの高さいっぱいに広がるセクション /
.dynamic-full-height-section {
height: 100dvh;
background-color: thistle;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 2em;
text-align: center;
}
/ 高さが動的に変わる背景やインタラクティブな要素 /
.interactive-element {
height: 50dvh; / Viewportの実際の高さの半分 /
/ … その他のスタイル … /
}
“`
dvh
のメリット
- 常に現在の表示領域にフィット: ツールバーの表示/非表示にかかわらず、要素の高さが常にViewportの実際の利用可能な高さに合わせられます。これにより、ツールバーが表示されている時は要素全体が画面内に収まり、ツールバーが非表示の時は余白なく画面いっぱいに広がります。
- 「動的ツールバー問題」を根本的に解決:
svh
で発生する余白、lvh
で発生する要素の隠れ、その両方の問題を同時に解決できます。これがdvh
が導入された最大の理由であり、最も期待される単位です。 - JavaScriptでのViewport高さ取得からの解放: 従来の開発では、この「実際のViewportの高さ」を取得するためにJavaScriptの
window.innerHeight
を使う必要がありましたが、dvh
を使えばCSSだけで完結できます。これは、開発効率とパフォーマンス(JavaScriptによるレイアウト変更はリフローを引き起こしやすい)の両面で大きなメリットです。
dvh
のデメリット
- 高さの動的変化: 要素の高さがユーザー操作に応じて変化するということは、一部のレイアウトやアニメーションにとっては予期しない挙動となる可能性があります。高さの変化によって他の要素が押しのけられたり、レイアウトに影響が出たりしないか注意が必要です。
- パフォーマンスとブラウザの実装: 高さの変化は要素の再描画やレイアウト計算(リフロー)を引き起こします。多くの要素が
dvh
を使用していたり、複雑なレイアウトで使われたりする場合、特にスペックの低いデバイスではパフォーマンスへの影響や、高さ変化の際にわずかなちらつきが見られる可能性が理論上はあります。ただし、現代のブラウザはこれらの最適化が進んでいます。 - デバッグの複雑性: 高さが常に変化するため、開発者ツールで要素の高さを確認する際に、ツールバーの状態を意識する必要があります。
dvh
はどんな時に使うべきか?
- ヒーローセクションや全画面要素など、画面いっぱいに表示したいが、ツールバーが表示されても要素の下部が隠れるのは避けたい場合。
- ツールバー非表示時に余白ができてしまうのも避けたい場合。
- JavaScriptの
window.innerHeight
と同等の挙動をCSSだけで実現したい場合。 - 要素の高さが動的に変化することを受け入れられる、あるいはその変化がデザインとして望ましい場合。
dvh
は、モバイルブラウザの動的なViewportに最も柔軟に対応できる単位です。多くのケースで「動的ツールバー問題」に対する理想的な解決策となり得ますが、高さ変化の挙動を理解し、デザインや他の要素への影響を考慮して使用することが重要です。
幅の単位:svw
, lvw
, dvw
について
高さの単位と同様に、幅についても新しいViewport単位が定義されています。
svw
(Small Viewport Width): Viewportの「最小」の幅(ツールバーなどが表示されていても確保される幅)の1%。lvw
(Large Viewport Width): Viewportの「最大」の幅(ツールバーなどが非表示になった場合の幅)の1%。dvw
(Dynamic Viewport Width): 現在のViewportの実際の幅の1%。
ただし、高さの動的ツールバー問題ほど、幅の動的ツールバー問題は一般的ではありません。モバイルブラウザのツールバーは通常、Viewportの高さを変化させますが、幅は(回転などがない限り)一定であることが多いからです。
しかし、特定の状況(例: 分割ビュー、特殊なキーボード表示、サイドに表示されるツールバーなど)ではViewportの幅も動的に変化する可能性があります。そのような稀なケースや、将来的なUIの変化に備えるために、幅の新しい単位も用意されています。
使用方法や挙動の考え方は高さの単位と同様です。特定の幅の変動に対応する必要がある場合に検討すると良いでしょう。多くの一般的なレスポンシブデザインにおいては、引き続きvw
を使用しても問題ない場合が多いですが、最新の仕様を理解しておくことは無駄ではありません。
各単位の比較と使い分け
ここで、従来のvh
と新しいsvh
, lvh
, dvh
を比較し、それぞれの使い分けについてまとめます。
単位 | 基準となるViewportの高さ | 挙動 | ツールバー表示時 | ツールバー非表示時 | 主なメリット | 主なデメリット | 適したユースケース |
---|---|---|---|---|---|---|---|
vh |
多くの場合、ツールバー表示時の高さ(ブラウザ依存あり) | 高さ固定 (ブラウザ依存) | 画面に収まる/一部隠れる | 余白ができる/画面いっぱい | 広く普及しており互換性がある (デスクトップ) | モバイルでの動的ツールバー問題を引き起こしやすい | デスクトップ中心のサイト、モバイル問題が許容される場合 |
svh |
ツールバーが常に表示されている状態の高さ(最小の高さ) | 高さ固定 | 常に画面に収まる | 余白ができる | レイアウトが安定する、要素が隠れない | ツールバー非表示時に余白ができる | 固定ヘッダー/フッター間のコンテンツ、レイアウトの安定性重視 |
lvh |
ツールバーが非表示になっている状態の高さ(最大の高さ) | 高さ固定 | 一部隠れる | 常に画面いっぱい | 画面領域を最大限に活用できる、余白ができない | ツールバー表示時に要素が隠れる可能性がある | 全画面ヒーローセクション、モーダル(没入感重視) |
dvh |
その瞬間のViewportの実際の高さ | 高さ動的変化 | 常に画面に収まる | 常に画面いっぱい | 常に実際の表示領域にフィット、JS不要、問題を根本解決 | 高さ変化による影響、パフォーマンス(実装依存) | 常に画面いっぱいに表示したい要素(隠れも余白も避けたい)、JS代替 |
どの単位を選ぶべきか?
どの単位を選ぶべきかは、実現したいレイアウトの要件と、ユーザー体験における何を優先するかによって異なります。
-
レイアウトの安定性を最優先し、ツールバー非表示時の余白を許容できる場合:
svh
を使用します。これは、ツールバーが表示された状態でのレイアウトを基準とし、要素がツールバーと重なって隠れることを確実に避けたい場合に適しています。固定ヘッダーやフッターの間に配置されるメインコンテンツ領域などに有効です。
-
画面領域の最大限の活用を最優先し、ツールバー表示時に要素の一部が隠れる可能性を許容できる場合:
lvh
を使用します。これは、ツールバーが非表示になった時の広い画面を活かして、没入感のある全画面表示を実現したい場合に適しています。ヒーローセクションや全画面モーダルなどに有効です。
-
常に現在のViewportの実際の高さにフィットさせたい場合(ツールバーの表示/非表示に応じて高さを変化させたい):
dvh
を使用します。これは、ツールバーが表示されても要素が隠れず、非表示になれば余白もできないという、最も柔軟で理想的な挙動をCSSだけで実現したい場合に適しています。多くの「画面いっぱいに表示したい」という要件において、dvh
が最適な選択肢となるでしょう。JavaScriptを使わずにwindow.innerHeight
相当の挙動を実現したい場合もこれです。
迷った時は?
- 多くの一般的なユースケース(例:画面いっぱいのヒーローセクション)では、
dvh
が最も現代的で柔軟な解決策となる可能性が高いです。ただし、高さが動的に変化することの影響を考慮する必要があります。 - もし
dvh
の動的な高さ変化による影響を懸念する場合、あるいはレイアウトの安定性を極めて重視する場合は、svh
を検討します。 - 非常に特殊なケースで、どうしてもツールバー非表示時の最大高さを基準にしたい(かつツールバー表示時の隠れを許容できる)場合にのみ、
lvh
を選択します。 vh
は、デスクトップ環境での利用や、新しい単位がサポートされていない古いブラウザへのフォールバックとして利用を検討する程度になるでしょう。モバイル環境でvh
を単独で使用することは、意図しないレイアウト崩れにつながるため推奨されません。
フォールバック戦略
新しいViewport単位は比較的新しいため、古いブラウザではサポートされていない可能性があります。このような場合のために、フォールバック(代替手段)を用意しておくと良いでしょう。最も簡単な方法は、古い単位を先に記述し、新しい単位を後に記述することです。CSSのカスケーディングルールにより、ブラウザが新しい単位を理解できればそちらが優先されます。
“`css
.dynamic-full-height-section {
/ フォールバック: 古いブラウザ向け /
height: 100vh;
/ 新しいブラウザ向け /
height: 100dvh;
}
“`
この例では、100vh
が先に適用されますが、ブラウザが100dvh
を解釈できる場合は、100dvh
で上書きされます。vh
のモバイルでの挙動はブラウザ依存があるため完璧なフォールバックではありませんが、何もないよりはマシなことが多いです。
より堅牢なフォールバックには、@supports
アットルールを使用する方法があります。これにより、ブラウザが特定のCSS機能をサポートしているかどうかを判定し、スタイルを適用できます。
“`css
.dynamic-full-height-section {
/ デフォルト (古いブラウザやフォールバック) /
height: 100vh;
}
@supports (height: 100svh) { / svh, lvh, dvh のいずれかで判定すればOK /
.dynamic-full-height-section {
/ 新しい単位がサポートされている場合 /
height: 100dvh;
}
}
“`
このように@supports
を使用することで、新しい単位に対応していないブラウザでは100vh
が、対応しているブラウザでは100dvh
が適用されるようになり、より意図した通りの挙動を実現できます。
ブラウザサポートと互換性
CSSの新しいViewport単位(svh
, lvh
, dvh
など)は、比較的新しい仕様ですが、主要なモダンブラウザではすでに広くサポートされています。
- 主要ブラウザ: Chrome (デスクトップ/Android), Firefox (デスクトップ/Android), Safari (デスクトップ/iOS), Edge (Chromiumベース) など、主要なブラウザの最近のバージョンではサポートされています。
- Safari (iOS): 特にモバイルSafariは、以前から
vh
の挙動に課題を抱えていましたが、新しい単位の導入により、この問題が標準的な方法で解決されるようになりました。iOS 15.4以降で完全にサポートされています。 - IE (Internet Explorer): IEはすでにサポートが終了しているため、これらの新しい単位には対応していません。IEをサポートする必要がある場合は、
vh
をフォールバックとして使うなどの対応が必要です。
最新の正確なサポート状況は、Can I Useのようなウェブサイトで確認することをお勧めします。「css-round-display-p3」や「css-viewport-units」などのキーワードで検索すると関連情報が見つかります。
実装における注意点:
- テストは必須: ターゲットとするデバイスやブラウザのバージョンで、必ずレイアウトが意図した通りに表示されるかテストを実施してください。特にモバイル環境では、異なるOSバージョンやブラウザアプリによって挙動が微妙に異なる可能性もあります。
- 段階的な機能向上: 新しい単位は、モダンブラウザ向けの機能向上として捉え、古いブラウザでも最低限のレイアウトが崩れないようにフォールバックを検討することが現実的です。
@supports
を活用することで、対応ブラウザではより良い体験を提供しつつ、非対応ブラウザでも許容範囲の表示を維持できます。
実践的なコード例
ここでは、新しいViewport単位を使った具体的なレイアウトのコード例をいくつか紹介します。
例1: 画面いっぱいのヒーローセクション
ツールバーの表示/非表示に関わらず、常に現在の画面高さいっぱいにコンテンツを表示したい場合。
“`html
ようこそ!
これはヒーローセクションです。
“`
“`css
.hero-section {
height: 100dvh; / ツールバーに合わせて高さを動的に調整 /
width: 100vw;
background-image: url(‘your-background-image.jpg’);
background-size: cover;
background-position: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
text-align: center;
}
/ フォールバックとしてvhも指定 /
@supports not (height: 100dvh) {
.hero-section {
height: 100vh;
}
}
/ あるいはシンプルなフォールバック /
/
.hero-section {
height: 100vh;
height: 100dvh;
…その他のスタイル…
}
/
“`
この例では、100dvh
を使用することで、モバイルでスクロールしてツールバーが隠れるとヒーローセクションの高さも広がり、余白なく画面いっぱいに表示されます。ツールバーが表示されれば高さが縮み、コンテンツが隠れるのを防ぎます。フォールバックとして100vh
を指定していますが、@supports
を使う方がより意図が明確で、現代的なアプローチです。
例2: 固定ヘッダー・フッター間のスクロール可能なコンテンツ領域
ヘッダーとフッターが固定されており、その間の領域でコンテンツをスクロールさせたい場合。ヘッダーとフッターはツールバーの表示状態に関わらず常に画面内に表示されてほしい。コンテンツ領域もツールバーが表示された状態でも隠れずに表示されてほしい。
“`html
ここにスクロール可能なコンテンツがたっぷり入ります。
コンテンツの終わりです。
“`
“`css
body {
margin: 0;
display: flex;
flex-direction: column;
/ Viewportの最小高さに合わせてボディ全体を配置 /
min-height: 100svh; / または height: 100svh; /
}
header {
height: 60px;
background-color: #f0f0f0;
flex-shrink: 0; / 高さ固定 /
}
footer {
height: 50px;
background-color: #e0e0e0;
flex-shrink: 0; / 高さ固定 /
margin-top: auto; / main-contentが縮んでもフッターを下に配置 /
}
.main-content {
/ 残りの領域を埋める /
flex-grow: 1;
overflow-y: auto; / コンテンツが溢れたらスクロール /
/ ヘッダーとフッターの高さを考慮して、Viewportの最小高さから計算 /
/ min-height: calc(100svh – 60px – 50px); / / ボディにmin-height: 100svh; を指定した場合は不要 /
background-color: lightgreen;
padding: 20px;
}
/ bodyにsvhがサポートされていない場合のフォールバック /
@supports not (min-height: 100svh) {
body {
min-height: 100vh;
}
.main-content {
/ 古いvhではヘッダー/フッターの高さ計算が必要になることも /
/ min-height: calc(100vh – 60px – 50px); / / vhの計算基準によっては必要 /
}
}
“`
この例では、body
要素にmin-height: 100svh;
を指定しています。これにより、ページの全体の高さがツールバーが表示されている状態の画面高さ以上になり、ヘッダーとフッターが必ず画面内に収まるようになります。main-content
はflex-grow: 1
で残りの領域を埋め、溢れたらスクロールします。svh
を使うことで、ツールバーが表示されてもヘッダーやフッターが画面外に押し出されたり、コンテンツ領域が隠れたりするのを防ぎます。ツールバーが非表示になった場合、body
の高さは100svh
で固定されているため、下部に余白ができますが、固定レイアウトではこの方が安定することが多いです。
例3: 全画面モーダルウィンドウ
画面全体を覆い隠すモーダルやオーバーレイ。ツールバーが非表示の時に画面いっぱいに広げたいが、ツールバーが表示された時もモーダル自体が隠れるのは避けたい。
“`html
“`
“`css
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
/ dvhを使用して、ツールバーに合わせて高さを動的に調整 /
height: 100dvh;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000; / 最前面に表示 /
/ 初期状態では非表示 /
visibility: hidden;
opacity: 0;
transition: opacity 0.3s ease, visibility 0.3s ease;
}
.modal-overlay.is-visible {
visibility: visible;
opacity: 1;
}
.modal-content {
background-color: white;
padding: 20px;
border-radius: 8px;
max-width: 90%;
max-height: 90dvh; / モーダル内容もdvHで制御 /
overflow-y: auto; / 内容が多ければスクロール /
}
/ フォールバック /
@supports not (height: 100dvh) {
.modal-overlay {
height: 100vh;
}
.modal-content {
max-height: 90vh;
}
}
“`
この例では、オーバーレイとモーダル内容の最大高さにdvh
を使用しています。オーバーレイは常に現在のViewportの実際の高さにフィットするため、ツールバーが表示されても非表示になっても、画面全体を正確に覆い隠します。モーダル内容のmax-height
もdvh
で指定することで、内容が長すぎてもモーダル自体がViewportから溢れてしまうのを防ぎつつ、現在の画面高さに合わせて最大限の領域を使用できます。これにより、ツールバーが表示されてもモーダル内容が隠れる可能性を減らすことができます。
例4: calc()
やmin()
, max()
, clamp()
との組み合わせ
新しいViewport単位は、他のCSS関数や単位と組み合わせて、さらに柔軟なレイアウトを作成できます。
“`css
/ 高さが常にViewportの実際の高さの半分か、最低でも300pxになる要素 /
.half-viewport {
height: max(300px, 50dvh);
background-color: orange;
}
/ 幅がViewportの実際の幅の80%で、最大800px、最低300pxの要素 /
.responsive-box {
width: clamp(300px, 80dvw, 800px);
background-color: purple;
margin: 20px auto;
padding: 20px;
color: white;
text-align: center;
}
/ 固定ヘッダー (60px) とフッター (50px) の間の領域に背景画像を表示 /
.main-background {
/ Viewportの実際の高さからヘッダーとフッターの高さを引く /
height: calc(100dvh – 60px – 50px);
background-image: url(‘another-image.jpg’);
background-size: cover;
background-position: center;
margin-top: 60px; / ヘッダーの下に配置 /
margin-bottom: 50px; / フッターの上に配置 /
}
“`
これらの例のように、dvh
, svh
, lvh
をcalc()
, min()
, max()
, clamp()
といった関数と組み合わせることで、より複雑で洗練されたレスポンシブデザインの要件を満たすことができます。特にcalc()
は、固定ピクセル値とViewport単位を組み合わせた計算に非常に役立ちます。
実装上の注意点と考慮事項
新しいViewport単位、特にdvh
を使用する際には、以下の点に留意が必要です。
- パフォーマンス:
dvh
は高さが動的に変化するため、ブラウザはスクロールイベントなどに反応して要素のサイズを再計算し、再描画を行う必要があります。要素の数が非常に多い場合や、複雑な描画を含む場合に、低スペックなデバイスではパフォーマンスにわずかな影響が出る可能性もゼロではありません。しかし、一般的な使用においては、現代のブラウザはこれらの最適化が進んでいるため、大きな問題になることは少ないでしょう。もしパフォーマンスが気になる場合は、開発者ツールのパフォーマンスプロファイリング機能などを活用してボトルネックを特定すると良いでしょう。 - 要素のちらつき:
dvh
による高さの動的変化が、ブラウザの実装によってはわずかながら要素のちらつき(特に境界線や背景など)として視覚的に感知される可能性があります。ほとんどのモダンブラウザではこの問題は解決されていますが、念のため複数のデバイスでテストを行うことを推奨します。 - デバッグ:
dvh
で指定された要素の高さは、開発者ツールで確認する際に、その瞬間のViewportの実際の高さに基づいた値として表示されます。ツールバーの表示/非表示状態を切り替えながら高さを確認することで、意図した通りの挙動になっているか検証できます。 - iOS Safari特有の挙動: 以前のiOS Safariでは、スクロール開始時と終了時にViewportの高さが変化し、その中間では変化しないという挙動が見られることがありました。新しい単位の導入により標準的な挙動に近づいていますが、古いiOSバージョンでは依然として微妙な挙動の違いがある可能性も考慮しておきましょう。
box-sizing
プロパティ:height
やwidth
プロパティにViewport単位を使用する場合、要素のパディングやボーダーの扱いをどうしたいかに応じてbox-sizing: border-box;
やbox-sizing: content-box;
を適切に設定することが重要です。特にborder-box
を使用すると、指定したheight
やwidth
にパディングやボーダーが含まれるため、レイアウト計算が直感的になります。- JavaScriptによる代替:
dvh
がサポートされていない環境や、CSSでは実現できない複雑な計算が必要な場合は、引き続きJavaScriptのwindow.innerHeight
を使用してViewportの実際の高さを取得し、要素の高さに反映させるという方法も有効です。ただし、CSS単位で完結できるならその方が推奨されます。
これらの注意点を理解し、適切に対応することで、新しいViewport単位を効果的に活用できるでしょう。
よくある質問 (FAQ)
Q1: dvh
は常にJavaScriptの window.innerHeight
と同じですか?
A1: dvh
は概念的にはJavaScriptのwindow.innerHeight
に非常に近いです。どちらもその瞬間のViewportの実際の表示領域の高さを示します。ただし、厳密にはブラウザの実装の詳細(例えば、どのタイミングで値が更新されるか、計算の小数点以下の精度など)によってわずかな違いが生じる可能性はあります。重要なのは、dvh
を使えばJavaScriptを書かずにCSSだけで同等の動的な高さを実現できるという点です。これは、コードの簡潔化、パフォーマンスの向上、保守性の向上といったメリットをもたらします。
Q2: vh
はもう使わない方が良いですか?
A2: モバイル環境での「画面いっぱいの高さ」を意図する場合、vh
は「動的ツールバー問題」を引き起こす可能性があるため、svh
、lvh
、またはdvh
を使用することを強く推奨します。特にdvh
が多くのケースで適切な解決策となります。
しかし、vh
が引き続き有用な場面もあります。例えば、
- Viewportの高さに対する相対的な単位として、単に要素の高さを指定したい場合(必ずしも画面いっぱいにする必要がない場合)。
- デスクトップ環境のみをターゲットとする場合(この場合、
vh
の挙動は安定的です)。 - 新しいViewport単位がサポートされていない古いブラウザへのフォールバックとして。
したがって、「もう使わない方が良い」というよりは、「モバイル環境での全画面表示には推奨されない」と理解するのが適切です。目的とターゲットブラウザに応じて使い分けることが重要です。
Q3: svh
, lvh
, dvh
はmargin
やpadding
にも使えますか?
A3: はい、使えます。CSSの長さの単位が使用できるほとんどのプロパティ(例: width
, height
, min-width
, min-height
, max-width
, max-height
, margin
, padding
, font-size
, top
, left
, bottom
, right
, transform: translate(...)
など)で、これらの新しいViewport単位を使用できます。これにより、要素のサイズだけでなく、要素間の余白や配置もViewportのサイズに応じて柔軟に設定できます。
Q4: 幅の単位(svw
, lvw
, dvw
)はどんな時に使いますか?
A4: 前述のように、モバイルブラウザのツールバーは通常、Viewportの幅には影響しません。したがって、多くの一般的なケースではvw
をそのまま使用しても問題ありません。しかし、タブレットの分割ビュー機能、特定の仮想キーボードが表示される場合、またはブラウザUIが側面に表示されるような特殊な環境では、Viewportの幅も動的に変化する可能性があります。そのような場合に、高さの単位と同様の考え方でsvw
, lvw
, dvw
を使用することで、幅の変化にも対応できるレイアウトを構築できる可能性があります。
Q5: 100dvh
と100vh
で見た目が同じに見える時があるのですが?
A5: はい、あります。ツールバーが非表示になっている状態のモバイルブラウザでは、100dvh
はLarge Viewportの高さと等しくなります。もしそのブラウザで100vh
がLarge Viewportの高さと同じ基準で計算されている場合、見た目は同じになります。逆に、ツールバーが表示されている状態では、100dvh
はSmall Viewportの高さと等しくなります。もしそのブラウザで100vh
がSmall Viewportの高さと同じ基準で計算されている場合、見た目は同じになります。問題は、多くのモバイルブラウザで100vh
が常にSmall Viewportの高さを基準に計算される傾向があり、ツールバー非表示時に余白ができることでした。dvh
は、その状況に応じて正確な現在の高さを取得するという点で異なります。ブラウザの実装やOSのバージョンによってvh
の挙動が異なる可能性があるため、新しい単位の利用が推奨されるのです。
まとめ:モバイルViewportのレイアウトをマスターするために
本記事では、CSSのViewport単位、特にモバイル環境における「動的ツールバー問題」に焦点を当て、従来のvh
単位の限界と、それを克服するために導入された新しい単位svh
, lvh
, dvh
について詳しく解説しました。
- 従来の
vh
はモバイルブラウザの動的なUIに対応できず、予期しない余白やコンテンツの隠れといった問題を引き起こしていました。 - 新しいViewport単位は、この問題を解決するために、Small (最小), Large (最大), Dynamic (動的) という3つの異なるViewport高さの基準を提供します。
svh
はツールバー表示時の最小高さを基準とし、レイアウトの安定性や要素が隠れるのを防ぐのに適しています。ただし、ツールバー非表示時に余白ができます。lvh
はツールバー非表示時の最大高さを基準とし、画面領域の最大限の活用や余白をなくすのに適しています。ただし、ツールバー表示時に要素が隠れる可能性があります。dvh
はその瞬間のViewportの実際の高さを基準とし、ツールバーの表示/非表示に関わらず常に現在の表示領域にフィットします。多くのケースで「動的ツールバー問題」に対する最も理想的な解決策となり、JavaScriptなしでwindow.innerHeight
相当の挙動を実現できます。ただし、高さが動的に変化することによる影響に留意が必要です。
これらの新しい単位を適切に使い分けることで、モバイルデバイスにおけるウェブサイトのレイアウトをより正確に制御し、ユーザーにストレスのない、意図した通りの体験を提供できるようになります。
現代のウェブ開発において、モバイルViewportの挙動を深く理解し、これらの新しい単位を効果的に活用することは、高品質なレスポンシブデザインを構築するための重要なスキルです。ブラウザサポートも広がっており、今こそこれらの単位を積極的にプロジェクトに導入する良い機会です。
まずは簡単な要素からsvh
、lvh
、dvh
を試してみてください。そして、ご自身のプロジェクトの要件やデザインに合わせて、最適な単位を選択し、必要に応じてフォールバック戦略も検討しましょう。
CSSの進化は続いており、開発ツールもそれに対応して進化しています。新しい単位を使いこなし、モバイル時代のウェブデザインをさらに洗練させていきましょう。
この記事が、あなたのCSSスキル向上の一助となれば幸いです。最後までお読みいただき、ありがとうございました。