CSSのビューポート単位(svh, lvh, dvh)でUI表示に合わせたスタイルを適応させる



スマートフォンやタブレット端末でのWebデザインでは、ツールバー、アドレスバーのUIが表示によってデザインが少しズレたりします。

iOSのSafariをはじめ、スマートフォンやタブレット端末でのツールバーやアドレスバーを含む100vhの表示問題は、「-webkit-fill-available」を指定して対応してきたと思いますが、calc関数等での計算を伴う場合は引数として使えなかったり、またブラウザによってはPCでも適応されてしまうなど、対応方法としてはそれほど安定するものではありませんでした。

CSS Values and Units Module Level 4 (6.1.2.1. The Large, Small, and Dynamic Viewport Sizes)で追加された新しい単位「sv* / lv* / dv*」を使うことで、UIの表示を踏まえたスタイルの指定ができるようになります。

以下、追加された単位になります。

sv*: Small Viewport(スモールビューポート)
UI(ツールバー、アドレスバー等)が表示されたときのviewportの大きさ。
lv*: Large Viewport(ラージビューポート)
UI(ツールバー、アドレスバー等)が表示されていないときのviewportの大きさ。
dv*: Dynamic Viewport(ダイナミックビューポート)
UI(ツールバー、アドレスバー等)の表示・非表示を考慮した、現在の表示に合わせたviewportの大きさ。


これらの単位はこれまでの「vw, vh, vmin, vmax」などの単位と同じように、min(ビューポートの短辺に対する割合)やmax(ビューポートの長辺に対する割合)を対象とする指定もあります。

Large Viewport (lvw, lvh, lvmin, lvmax)
Small Viewport (svw, svh, svmin, svmax)
Dynamic Viewport (dvw, dvh, dvmin, dvmax)



今回は、よくあるスマートフォンやタブレット端末のUIに合わせるよう、高さを調整する「svh、lvh、dvh」について見ていきます。

svh: small viewport heigh
UIが表示されていないときのviewportの高さ。
lvh: large viewport heigh
UIが表示されていないときのviewportの高さ。
dvh: dynamic viewport heigh
現在の表示に合わせたviewportの高さ。
CSSのビューポート単位(svh, lvh, dvh)




Webブラウザのサポート状況は、viewport単位でまとめて確認できます。

Can I use(Large, Small, and Dynamic viewport units)
https://caniuse.com/viewport-unit-variants

Google ChromeやMicrosoft Edge、Safari、Firefoxと、主要ブラウザはサポートされています。

ビューポート単位(svh, lvh, dvh)で高さを調整


基本的にはheightプロパティで使っていきますが、一応サポートされていないWebブラウザにも対応するため、フォールバック用のスタイル「height: 100vh;」を前に記述し、これまでのvhと併用して使用しましょう。

.foo {
    height: 100vh;
    height: 100dvh;
}



それではサンプルを交えて使い方を見てみましょう。
まずはHTMLから。

HTML

<main>

  <section class="section-conts firstView">
    <div>
      <h1>First View</h1>
      <p>height: 100dvh;</p>
    </div>
  </section>

  <section class="section-conts">
    <h2>section 2</h2>
    <p>height: 100lvh;</p>
  </section>

  <section class="section-conts">
    <h2>section 3</h2>
    <p>height: 100svh;</p>
  </section>

  <section class="section-conts">
    <h2>section 4</h2>
    <p>height: 100dvh;</p>
  </section>

</main>



ファーストビューから簡単なセクションを構築して見ました。

続いてはCSS。
表示領域に合わせた高さの調整と共に、背景画像を設定するセクションも用意しました。

CSS

.section-conts {
  padding: 4%;
  text-align: center;
  font-weight: bold;
  height: 100vh; /* fallback for browsers that doesn't support */
}

.section-conts.firstView {
  height: 100dvh;
  background: url(../images/mv.jpg) no-repeat right center;
  background-size: cover;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
}

.section-conts:nth-child(2) {
  height: 100lvh;
  background-color: rgb(255, 190, 190);
}

.section-conts:nth-child(3) {
  height: 100svh;
  background: url(../images/bg.jpg) no-repeat center bottom;
  background-color: rgb(190, 190, 255);
}

.section-conts:nth-child(4) {
  height: 100dvh;
  background-color: rgb(190, 255, 190);
}



ファーストビューではアドレスバーが表示されるので、svhで高さを指定していくと思いますが、ユーザー側でアドレスバーを非表示にすることを想定するのであれば、ファーストビューではdvhで高さを指定した方が臨機応変に対応できるでしょう。

ビューポート単位(svh, lvh, dvh)での高さ調整



スクロールして閲覧するコンテンツでsvhで高さが指定してあると、アドレスバーの表示が前提の高さとなります。背景画像を設定しているとよくわかります。
高さによる微妙な表示崩れは、lvhの設定で調整すると良いでしょう。

スクロールして閲覧するコンテンツの高さ調整(svh, lvh, dvh)



自動で調整する場合はdvhを指定しましょう。

以下、ここまでの実装になります。
動画(3分)

まとめ


今回は高さの単位について見てきましたが、横幅では同じように「svw, lvw, dvw」と単位が指定できます。

他、vi(svi, lvi, dvi)などインライン方向のviewportのサイズや、vb(svb, lvb, dvb)といったブロック方向のviewportのサイズの単位もあります。

主にスマートフォンやタブレット端末での高さを調整することが多いと思います。
これまで微妙にズレていた表示も、新たに追加されたビューポート単位で調整していけることでしょう。