背景画像だけをフェードインで表示させる方法
- 公開日 : 2015年6月26日
- カテゴリ : Web制作
昨日、画面全体が表示されてから数秒後、浮き出るように画像を表示するのページで説明したように、横幅1500ピクセル以上のディスプレイでこのブログを表示すると鳳凰の画像がふわっと現れる。(フェードインという)
仮にこの画像をimg要素としてフェードインさせるのならば、jQueryのfadeInメソッドを使用すれば最も簡単に実装できるだろう。
参考URL:jQuery日本語リファレンス・fadeIn
しかし、実はそのやり方では問題が発生する。
今回のようにコンテンツ幅より横幅の大きい画像をimg要素として出現させると、本来は以下の画像のようなコンテンツ幅だったのが、
img要素を出現させることによって以下のようにコンテンツ幅が広がってしまう。(未検証だがおそらく)
コンテンツ幅が上画像のように広がると、それに応じてブラウザの横スクロールバーが出てしまったりと別の新たな問題が発生してしまうことになる。
これではまずい。
それを避けるためには、画像をimg要素ではなくCSSの背景画像として表示させることになるだろう。
しかしここでも問題がある。
上記のjQueryのfadeInメソッドやanimateメソッドは背景画像だけをフェードインすることができないという点である。
その要素ごとフェードインさせることしかできない。
というわけで、今回はCSSの背景画像をフェードインさせる際の問題点とその解決法を解説します。
背景画像をフェードインさせるときに発生する問題点
CSSの背景画像をフェードインさせる手順のイメージとしては以下のようになります。
しかしここで発生する問題点は、このdiv要素内にコンテンツがある場合、そのコンテンツも上記3の段階で透明になってしまうという点である。
今回の目的はあくまでも「背景画像だけをフェードインさせる」というものなので、中にあるコンテンツまでもが透明になってはまずい。
ではどうするか?
上記問題点の解決法
解決法の手順としては以下のようになります。
このやり方のポイントは、2つのレイヤーを入れ子にしないことである。
入れ子にしてしまうと透明度の設定やフェードインの設定が両方に及んでしまうためです。(文末にある追記参照)
CSSのpositionプロパティとz-indexを使用して重ねてください。
具体的なソースの例
では、上記の手順を実現するためのソースの例を書いてみます。
- 1、コンテンツのレイヤーの背景色を透明にする。
-
<div class="contents-layer"></div>
.contents-layer{ background : transparent; /* 実際には記述しなくても初期値がtransparentである */ }
- 2、フェードインさせるレイヤーをコンテンツのレイヤーの背後にセット。さらに透明にしておく。(上記のように入れ子にしてはいけない)
-
<div class="fade-layer"></div> <div class="contents-layer"></div>
.fade-layer{ width : ***px; /* contents-layerと同じ大きさにする */ height : ***px; /* contents-layerと同じ大きさにする */ background : url(表示させる画像のパス) no-repeat 0 0; position : absolute; left : **px; /* contents-layerと同じ位置に合わせる */ top : **px; /* contents-layerと同じ位置に合わせる */ z-index : -1; opacity : 0; }
- 3、JavaScriptによって下のレイヤーをフェードインさせる。(fadeInメソッドでの例)
-
$('.fade-layer').fadeIn();
- (参考)fadeInメソッドではなくanimateメソッドの場合は以下のようになる。(フェードイン速度が800ミリ秒の場合)
-
$('.fade-layer').animate({ 'opacity' : '1' }, 800);
お好きなほうのやり方でどうぞ。
なお、上記手順2で「contents-layerと同じ大きさにする」という点で、仮にcontents-layerの横幅や縦幅が可変の場合(コンテンツによって変化する場合)はJavaScriptによってその大きさを取得し、手順2のCSS設定もJavaScript側で行ってしまえば良いでしょう。
問題点のところで説明したように入れ子にしないことが前提なので、空っぽである下のレイヤーを上のレイヤーの大きさに合わせられるかがミソになります。
追記:と、ここまで全部書いてから思いましたが、入れ子にしたとしても中のレイヤーをopacity : 1 !important;としておけば、下のレイヤーを透明にしても問題ないような気がします。(未検証)