全画面の背景画像をCSSのマウスホバーで切り替える(画像のプレロードあり)
全画面に設置した背景画像をマウスホバーで切り替える方法。全画面の背景画像を含め、全てCSSだけでやっています。
切り替えるだけであれば、間接セレクタを使ってマウスホバー時の背景画像を用意しておけばいいだけなので、結構簡単ですが、画像切り替えの際に読み込みのための遅延を無くしたかったので、頭を悩ませました。
いわゆる画像のプレロード(事前読み込み)ですが、JSを使わずにCSSだけでやる方法がないか模索した結果、以下の様な形となりました(プリロードとも言う)。
プレロードなしの場合
まずは、画像のプレロードがない場合のものです。つまり、オンマウスの時に初めて画像を読み込むということになり、背景画像が切り替わる際に若干の遅延(タイムラグ)が生まれるんですね。これは初めての時だけで、2回目のオンマウス時には既に画像が読み込まれているので、遅延は生じません。
【DEMO】全画面の背景画像をCSSのマウスホバーで切り替える(プレロードなし)
実際にオンマウスしてみると、初回のマウスホバーでは切り替わるまでに時間がかかり、(ブラウザにもよりますが)画面が一瞬白くなり、オンマウスの時点で画像が読み込まれているのが分かると思います。
2回目のマウスホバーでは、既に画像が読み込まれているので、スムーズに切り替わります。なお、ブラウザの設定にもよりますが、遅延が確認できるのはキャッシュの関係上、初回訪問時のみとなります(ブラウザを再起動すれば再度確認できるかも)。
以下、HTMLとCSSです。
HTML
<body>
<!-- ボタン -->
<div class="bg-change no1">hover1</div>
<div class="bg-change no2">hover2</div>
<div class="bg-change no3">hover3</div>
<!-- コンテンツ -->
<div class="wrapper">
<div class="contents">
<!-- 省略 -->
</div>
</div>
</body>
HTMLでのポイントは、間接セレクタを使用するため、マウスホバーの対象となるボタン類を、コンテンツの前にもってきていることです。
CSS
/* ボタンのスタイル */
.bg-change {
position: absolute;
top: 0;
bottom: 0;
width: 200px;
height: 50px;
line-height: 50px;
margin: auto;
text-align: center;
color: #fff;
background: rgba(0,0,0,.4);
cursor: pointer;
}
.bg-change.no1 {
right: 66%;
}
.bg-change.no2 {
left: 0;
right: 0;
}
.bg-change.no3 {
left: 66%;
}
/* コンテンツのスタイル */
.wrapper {
width: 100%;
height: 100%;
}
.contents {
height: 100vh;
background-image: url(/* 背景画像のURL */);
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
/* ボタンホバー時のスタイル */
.bg-change.no1:hover ~ .wrapper .contents {
background-image: url(/* ホバー背景画像1のURL */);
}
.bg-change.no2:hover ~ .wrapper .contents {
background-image: url(/* ホバー背景画像2のURL */);
}
.bg-change.no3:hover ~ .wrapper .contents {
background-image: url(/* ホバー背景画像3のURL */);
}
背景画像は.contents
に指定していますが、.wrapper
に指定でもいいと思います。全画面はheight:100vh
とbackground-size:cover
で簡単にやってしまっています。ボタンの位置とかは適当です。
背景画像の切替えは、間接セレクタを使って、各ボタンをホバーした際のbackground-image
のURLをそれぞれ用意しておくことで行っています。
プレロードありの場合
続いてプレロードありの場合のものです。以下のリンクからデモを確認できます。プレロードなしの場合のものと同じ画像を使用していますが、画像ファイル自体は名前を変え、全く別のものとなっていますので、キャッシュ等の影響は受けないようになっています。
【DEMO】全画面の背景画像をCSSのマウスホバーで切り替える(プレロードあり)
オンマウスすると、初回のマウスホバーでもスムーズに背景画像が切り替わることが確認できると思います。
どのようにやっているのかは以下の通りです。HTMLはプレロードなしの場合のものと全く同じなので省略しています。
CSS
/* ボタンのスタイル */
/* プレロードなしの場合のものと同じなので省略 */
/* コンテンツのスタイル */
.wrapper {
width: 100%;
height: 100%;
}
.contents {
height: 100vh;
background-image: url(/* 背景画像のURL */), url(/* ホバー背景画像1のURL */), url(/* ホバー背景画像2のURL */), url(/* ホバー背景画像3のURL */);
background-position: center;
background-repeat: no-repeat;
background-size: cover, 0 0, 0 0, 0 0;
}
/* ボタンホバー時のスタイル */
.bg-change.no1:hover ~ .wrapper .contents {
background-image: url(/* ホバー背景画像1のURL */);
background-size: cover;
}
.bg-change.no2:hover ~ .wrapper .contents {
background-image: url(/* ホバー背景画像2のURL */);
background-size: cover;
}
.bg-change.no3:hover ~ .wrapper .contents {
background-image: url(/* ホバー背景画像3のURL */);
background-size: cover;
}
プレロードは、.contents
のbackground-image
に背景画像URLを複数指定することで行っています。この場合、画像の読み込みは、ページが開かれたと同時に行われるので、プレロードとしてちゃんと機能するようになります。
また、表示させたい背景画像以外は非表示にしないといけないので、複数URL指定の際の最初に設定した背景画像が最前面に表示される性質を利用し、background-position
をcenter
に統一して、全ての背景画像を同じ位置にし、かつ、念のため、background-size
をゼロにして最前面の画像以外は表示させないようにしています。
ちょっと分かりづらいかもしれませんが、一応これで、プレロードを伴ったマウスホバーでの背景画像の切り替えをCSSだけで行うことができました。
まとめ
応用として、.contents
にtransition
を指定すれば、アニメーションが効いて、よりスムーズな背景画像の切り替えが行えるようになります。
ただ、ブラウザによって少々問題があったため、今回はアニメーションを指定しませんでした。具体的に言うと、Chromeでは、transition
を指定すると初回のオンマウス時のみ(画像を読み込む時のような遅延とは別の)遅延が発生し、Firefoxではそもそもbackground
をtransition
でアニメーションをさせることができませんでした。唯一、Safari(Mac)での表示が一番自然でした。
アニメーションは使えないかもしれませんが、プレロードを伴った背景画像の切り替えとして、すごくシンプルに実現できる方法なのではと思います。