(この記事は2018年10月現在です。今後、この記事の情報はあてにならなくなるかもしれません。ご注意ください。)
こんにちは、51代CG研のえすふりです。
さて、今日のテーマはWebデザインです。Webデザインにおいて、画面いっぱいに写真やイラストをどーんと表示させてみたいな、と思うことはありませんか?
そんなとき、とっても便利なCSSがありますよね。
そうです、「100vh」です。
簡単に言うと、デバイスの高さを100等分したものが1vhであり、それを100倍した100vhではデバイスの高さいっぱいに高さを指定できる、という意味です。
つまり、理論上は100vhによって画面いっぱいにどーんと表示が出来るはずなのです。(これは「フルスクリーンレイアウト」と言います。)
しかし、この100vh、スマホ(実はタブレットも)においては諸悪の根源になりがちなのです。
(スマホ100vh問題における個人的対応策は一番下にまとめました。それだけ見たい方はどーんと下にスクロールしちゃってください。)
とりあえず見てみよう
さて、スマホ100vh問題とは、デバイスによって挙動が変わってしまうことなのです。 とりあえず、みなさんお持ちのスマホで https://sufurin.github.io/100vh-01/ を見てみましょう。
このページの目的は、画像を画面いっぱいに表示させ、画像中央(すなわちデバイス中央)に文字を置きたい、というもの(わりとありがちなシーンかな、と思います)です。
私が確認した環境は、iPhone 8のSafari、Chromeの各(ブラウザ)アプリケーションです。
ファーストビュー
iPhone 8 - Safari, Chrome
同じiPhone 8で、同じページを見ているにも関わらず、見え方が大きく異なっていることが確認できます。
例えば、
・画像の見えている範囲が違う
・Safariにおいて、明らかにデバイス中央に文字が無い
などが挙げられます。
なぜこうなってしまうのか、という質問に対する答えはネットの海にたくさん転がっています。
要するに、Safariの場合、アドレスバー(スマホ上部のアドレスが書いてある部分)の高さを100vhに含んでしまうため、アドレスバー分の高さが下にずれてしまうのです。結果として、デバイス中央にあるべき文字が、アドレスバー分下にずれてしまうのです。
さて、この時点でスマホ100vhの闇が垣間見えた気がしてきましたか?
下にスクロール
iPhone 8 - Safari
iPhone 8 - Chrome
さてさて、Safariだといい感じ(というか普通)にスクロールしてくれました。
一方、Chromeでスクロールすると、画像が大きくなってる///という挙動が確認されます。これ、実際にスマホで体験していただくと分かるんですが、なかなか「うーん……」という感じがしてしまうのです。あーもうめちゃくちゃだよ。
嘆いていても仕方ないので、大きくなっちゃう理由を考えます。以下、一部推測を含むのでご注意ください。
Chromeはアドレスバーを含まない高さを100vhとしています。簡単に言うと、「見えている範囲」が100vhです。
これをスクロールしたらどうでしょうか。
なんとアドレスバーが引っ込み、見えている範囲が拡大します。それにつられて、100vhが再計算されてしまう、というオチなわけです(たぶん)。
逆にSafariの場合だと、アドレスバーの高さも含めて100vhとしていたため、見えている範囲が変わったところで100vhが再計算されることはありません(たぶん)。
SafariとChrome、どっちで見ても難ありな100vhパイセン……。スマホ100vhの闇が思う存分感じられたでしょうか。
じゃあどうすんの
諦めたら画面いっぱいにどーんできなくなるやろ! という意見をお持ちの方、いやいや、CSSがダメならアレがあるじゃないですか。
そう、「 jQuery (JavaScript)」が。
(余談)
jQueryについて調べてみると結構ネガティブな記事(「まだ使ってるの」とか「オワコン」とか)が散見されます。なので、え、じゃあ辞めとこ……となる人がいるかもしれません。が、あくまで一サークルの「ホームページ制作担当」であれば、ネット上に転がってるjQueryコードをコピペして、クラスやIDを書き換えて実際に使えるくらいができれば十分だと思います(Webアプリケーションを作りたいなら話は別だと思います(知らんけど))。
PCは「CSS: 100vh」、スマホは「jQuery: $(window).height()」
まずは、例によってお持ちのスマホで https://sufurin.github.io/100vh-02/ をご覧ください。
このやり方だと、おそらく先程のようなブラウザによってファーストビューの見え方が違うという問題や、スクロール時に挙動がおかしいといった諸問題が解決していることが感じられるかと思います。(ただ、2枚目以降はブラウザによっていっぱいでは無くなるという問題が発生してしまいましたが……。ファーストビューだけ画面いっぱいにしたいという場合なら問題ありません。)
HTML/CSS
vhを使わずにファーストビュー(だけ)を画面いっぱいかつ文字をその画像中央にする場合はこんな感じにします(2枚目以降はブラウザによって異なってしまいます)。 ポイントとしては、スマホやタブレットだけjQueryを適用させ、PCはCSSを適用させたいという点です。
なぜかというと、PCであれば100vhで構わないということはもちろん、このjQueryはアドレスバーのせいでリサイズをされることを防ぐためのコードなので、PCでこれが適用されてしまうと、PCにおいてもウィンドウの高さを変えたところでその高さに応じてリサイズされることが無くなってしまうからです。
HTML
<body>
<div class="bg_pc bg_sp bg_01">
<h1 class="h1_sp">わーい</h1>
</div>
<script>
$(document).ready(function(){
var heightSize = $(window).height();
var titlePosition = heightSize / 100 * 47.5;
var titleSize = heightSize / 100 * 5;
$('.bg_sp').height(heightSize);
$('.h1_sp').css("padding-top", titlePosition);
$('.h1_sp').css("font-size", titleSize + "px");
});
</script>
</body>
CSS
body, h1{
margin: 0;
}
.bg_01{
background-image: url(使用したい画像);
background-size: cover;
}
h1{
font-family: sans-serif;
text-align: center;
color: #fff;
}
@media screen and (min-width: 960px) { /* スマホとタブレット以外はこっちを適用 */
.bg-pc{
height: 100vh !important; /* !importantを使用し、jQueryを打ち消し */
}
h1{
padding-top: 47.5vh !important; /* !importantを使用し、jQueryを打ち消し */
font-size: 5vh !important; /* !importantを使用し、jQueryを打ち消し */
}
}
さて、別に文字は高さ中央じゃなくていいんだ、という場合はもうちょい簡単になります。
HTML
<body>
<div class="bg_pc bg_sp bg_01"></div>
<script>
$(document).ready(function(){
var heightSize = $(window).height();
$('.bg_sp').height(heightSize);
});
</script>
</body>
CSS
body{
margin: 0;
}
.bg_01{
background-image: url(使用したい画像);
background-size: cover;
}
@media screen and (min-width: 960px) { /* スマホとタブレット以外はこっちを適用 */
.bg-pc{
height: 100vh !important; /* !importantを使用し、jQueryを打ち消し */
}
}
この記事を書いた理由
ただの宣伝です。
この方法を利用し、早稲田祭特設サイトを作成しました。おそらく、スマホでもPCでも背景画像が高さいっぱいになっていると思います(そして、スクロール時におかしな挙動になることは無いと思います)。
ぜひMIS.Wブースにお越しください!
追伸
2018年9月より、Google Fontsにおいて一部の日本語フォントが正式にサポートされるようになりました。
これによって、「Noto Sans JP」はもちろん、「M PLUS 1p」や「Sawarabi Mincho」などが正式に使えるようになったことから、さらにWebデザインの幅が広がることが予想されます。
お気付きの方はいらっしゃるかもしれませんが、早稲田祭特設サイトは日本語フォントに「M PLUS 1p」を使用しています(宣伝)。