ヒーローイメージの高さや幅に100vhや100vwを使う際の問題点と解決策

ヒーローイメージの高さや幅に100vhや100vwを使う際の問題点と解決策

2021年1月6日

最近はWebサイトのファーストビューにヒーローイメージを使うことって多いですよね。

ヒーローイメージとはビューポートの全画面に表示する画像のことです。
レスポンシブWebデザインの場合、ファーストビューのビューポートは端末やウインドウサイズにによって変わりますが、ヒーローイメージにheight: 100vhwidth: 100vwと指定することで常にファーストビューと同じサイズを維持することが出来ます。

僕もこの方法がお手軽なので良く使っていましたが、いくつか問題点があることに気付きました。

ヒーローイメージに100vhや100vwを使う際の問題点

ヒーローイメージの高さや横幅に100vhや100vwを使う際はそれぞれ問題点があります。
この問題点はヒーローイメージだけではなく、全画面表示する要素には共通します。

高さに100vhを指定するとiPhoneのSafariで一部が隠れてしまう

iPhoneのSafariでWebサイトを開いた場合、ファーストビューの上部にアドレスバーが表示されます。
本来ならアドレスバーの下から画面の最下部までの領域にヒーローイメージを表示したいのですが、アドレスバーの高さだけヒーローイメージが画面の下にはみ出してしまいます。

ヒーローイメージの一部が画面の外にはみ出してしまう

ヒーローイメージの高さにheight:100vhを指定すると画像の下部が見切れてしまいます。

横幅に100vwを指定するとPCで横スクロールが発生する

例えばウィンドウの横幅が1000px、スクロールバーの横幅が20px、ビューポートの横幅が980pxだったとします。

ウインドウ、スクロールバー、ビューポートのサイズ

この場合、ヒーローイメージの横幅はビューポートと同じ980pxにしたいのですが、width:100vwを指定するとウインドウサイズの1000pxになってしまいます。

ヒーローイメージの一部(20px)はスクロールバーの下に隠れる様な状態となり、横スクロールが発生します。

横幅に100vwを指定すると横スクロールが表示される

スマートフォンやMacであればスクロールバーが常に表示されていないので問題ありませんが、Windowsは常にスクロールバーが表示されているのでこの問題が発生します。
Macも設定によっては常にスクロールバーが表示されるので、この場合も同じ問題が発生します。

僕は普段からMacで作業しているので、Windowsで横スクロールが表示されていることに気づいていませんでした。

ヒーローイメージの高さに100vhを使う場合の対策

ヒーローイメージの高さに100vhを指定するとiPhoneのSafariではアドレスバーの高さだけ画像が見切れてしまいます。
この問題への対策を2つ紹介します。

CSSで対策する方法

まずはCSSで対策する方法です。
少しハック的な方法になりますが、画面の高さいっぱいに表示したい要素にmin-height: 100vh;min-height: -webkit-fill-available;を指定することで希望通りの表示になります。

ただし、min-height: -webkit-fill-available;はPCのChromeで表示が崩れるので@supports (-webkit-touch-callout: none)を指定してChromeを除外します。

HTML

<div class="hero"></div>

CSS

.hero {
  min-height: 100vh;
}

@supports (-webkit-touch-callout: none) {
  .hero {
    min-height: -webkit-fill-available;
  }
}

デバイスの向きを変えても要素の高さが変わらないという情報もありましたが、iOS 14.2のSafariで検証したところ画面の高さに合わせて要素の高さも変わりました。

jQueryで対策する方法

次はjQueryで対策する方法をご紹介します。
CSSでの指定はあきらめて、jQueryで画面サイズに合わせて要素の高さを変える方法です。

HTML

<div class="hero"></div>

JavaScript

$(document).ready(function () {
  var windowHeight = $(window).height();
  $(".hero").height(windowHeight);
});
$(window).resize(function () {
  var windowHeight = $(window).height();
  $(".hero").height(windowHeight);
});

ページの読み込み時とウインドウサイズ変更時にウインドウサイズを取得して.heroの高さを指定します。

ハック的なCSSを使いたく無い場合はjQueryで対策する方法がおすすめです。

ヒーローイメージの横幅に100vwを使う場合の対策

何とか横幅を100vwで指定する方法は無いか調べましたが、いい方法は見つかりませんでした。
100vwを使うことは出来ませんが2つの解決策をご紹介します。

横幅に100vwではなく100%を指定する

シンプルにヒーローイメージの横幅を100vwではなく100%で指定すると解決します。
ただし、「ヒーローイメージの親要素の横幅 = ウインドウの横幅」でない場合は、意図した表示にならないので注意してください。

HTML

<div class="hero"></div>

CSS

.hero {
  width: 100%;
}

jQueryで対策する方法

ヒーローイメージの高さをjQueryで指定した方法と同様に横幅をしていします。
ただし、横幅はCSSでwidth: 100%;を指定する方がシンプルなのであまり使う機会は無いかもしれません。

HTML

<div class="hero"></div>

JavaScript

$(document).ready(function () {
  var windowWidth = $(window).width();
  $(".hero").width(windowWidth);
});
$(window).resize(function () {
  var windowWidth = $(window).width();
  $(".hero").width(windowWidth);
});

【まとめ】ヒーローイメージの高さと横幅を指定するベストな方法

僕はヒーローイメージの高さと横幅を以下の様に指定することにしました。

HTML

<div class="hero"></div>

CSS

.hero {
  width: 100%;
  min-height: 100vh;
}

@supports (-webkit-touch-callout: none) {
  .hero {
    min-height: -webkit-fill-available;
  }
}

もし、min-height: -webkit-fill-available;が上手く動作しない場合や、使いたく無い場合は高さをjQueryで指定する方法もありです。

HTML

<div class="hero"></div>

CSS

.hero {
  width: 100%;
}

JavaScript

$(document).ready(function () {
  var windowHeight = $(window).height();
  $(".hero").height(windowHeight);
});
$(window).resize(function () {
  var windowHeight = $(window).height();
  $(".hero").height(windowHeight);
});

以上、ヒーローイメージに100vhや100vwを指定する際の注意点と解決策の紹介でした。

参考にした記事

あ、iPhoneで見るとちょっとズレてますー そんな時はブラウザの高さを自動で取得しちゃえばOKですよー 画像
125naroom.com