「Pure CSS3 Cycle Slider」をお手本にして、css3のanimationで永久ループするスライドショーを作ります。
とても美しい動作ですので、まずは動作を確認して下さい。
- 画像にマウスホーバーすると、スライドが止まる
- マウスホーバーで画像に対応するh1が現れる
- スライドの表示秒数を伝える工夫もされている
マークアップをキチンと考える
最終的にCSSで動作させるのか、jQueryで動作させるのかに関わらず、まずはきちんとマークアップします。そうすると以下の利点があります。
- スライドの中身が、クリックさせたいリンクの列挙だとすれば、SEOの効果も望めます。単に画像を動かすのと、見出しタグ付きの要素が動いているのとでは大違いです。
- 対象ブラウザに合わせて、実装方法を選択できます。例えば、古いIEなどでも動かしたければ、古いIEにだけIEの条件コメントで自作のjQueryを読み込む、等。
- プログレッシブ・エンハンスメントへの対応も、ほとんど出来ていることになります。
ここでは『画像とその名前を含むリンクを箇条書きにする』と考えて ul > li > a > h2,img としてみました。div.progress-barは画像の下に表示させる「スライドの表示秒数を伝える工夫」の為の部品です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<div class="sample" title="SAMPLE 1"> <ul> <li> <h2>桃</h2> <p><a href="http://example.com"><img src="http://clubringo.com/wp-content/uploads/2013/02/slides_momo-150x150.jpg" alt="桃" width="150" height="150" class="alignnone size-thumbnail wp-image-665" /></a></p> </li> <li> <h2>栗</h2> <p><a href="http://example.com"><img src="http://clubringo.com/wp-content/uploads/2013/02/slides_kuri-150x150.jpg" alt="栗" width="150" height="150" class="alignnone size-thumbnail wp-image-667" /></a></p> </li> <li> <h2>柿</h2> <p><a href="http://example.com"><img src="http://clubringo.com/wp-content/uploads/2013/02/slides_kaki-150x150.jpg" alt="柿" width="150" height="150" class="alignnone size-thumbnail wp-image-666" /></a></p> </li> </ul> <div class="progress-bar"></div> </div> |
スライドさせる準備
同じhtmlに対して以下の目的でCSSを施します。
- 各<li>のリストマークを外す
- 各<li>をpositionの基準点にする
- 各h2をhover時にだけ表示させる
- お手本では縦にスライドしていますが、今回は横方向にスライドさせたいので、各<li>を横並びにする
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
.slide ul{ list-style:none; } .slide ul li{ float:left; width:150px; height:150px; position:relative; overflow:hidden; } .slide ul li h2{ position:absolute; padding:0.5em 1em; background:rgba(0,0,0,0.5); color:#fff; top:0; left:-160px; } .slide ul li:hover h2 { left:0px; } |
h2の出現時に動きをつける
hover時の演出にCSS3のtransitionを加えてみます。上記のSAMPLE 2との違いを、マウスオーバーして比べて下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.slide.transit ul li h2{ /* transitionの秒数を0.5秒に指定。その他の指定はdefaultに任せました。 -moz-はFirefox用のベンダープレフィックスで、 -webkit-がSafariとChrome用のベンダープレフィックスです。 */ -moz-transition:0.5s; -webkit-transition:0.5s; transition:0.5s; /*フワッと表示される様に不透明度も設定*/ opacity:0; } .slide.transit ul li:hover h2 { /*不透明度が0%から100%になるように*/ opacity:1; } |
要素Aにtransionプロパティをつけると、要素Aが要素A’に変化する「途中」をアニメーションの様に表示できます。Adobe Flashを使ったことがある人は、タイムラインのキーフレームを設定する、と考えるとイメージし易いかもしれません。
要素にマウスオーバーするとhover疑似クラスが付いて、AからA’に変化しますから、これを利用するのが最も使えるパターンです。
他にもtarget、active、select疑似クラスも使えます。また、jQueryでclassを操作しても良いでしょう。
各<li>にCSS3のanimationを設定する
transitionとanimationは似ていますが、いくつかの点で大きく異なります。整理してみましょう。
注目ポイント | transition | animation |
---|---|---|
再生秒数の設定 | transition-duration | animation-duration(CSSのショートハンドで指定する場合は先に書かれた秒数)。デフォルトは0秒なので何らかの時間を指定することになる。 |
開始時間を遅らせる | transition-delay | animation-delay(ショートハンドで指定する場合は後に書かれた秒数) |
イージングの使用 | transition-timing-function | animation-timing-function |
変化させるcssプロパティの選択 | transition-property | キーフレームの中で指定する。 |
キーフレームの使用 | できない | animation-nameで指定する。必須。 |
繰り返しの回数の指定 | できない | animation-iteration-count(0以上の整数か、infiniteで永久にループを指定できる) |
繰り返しの方向指定 | できない | animation-direction(normalで毎回0→100%で動く。alternateで、偶数回は100→0%へと逆方向に動く。) |
一時停止 | できない | animation-play-state(runningで動く。pausedで一時停止) |
アニメーションの実行前や実行後のスタイル指定 | できない | animation-fill-mode(none , forwards , backwards , both が指定可能。) |
スライドショーの場合は、ループさせ続ける必要があるので、animationを使用する訳です。div#sampleAnimeをanimationさせてみましょう。
CSS3のanimationの指定は以下の様に行います。
- 動かしたい要素のセレクターにanimationプロパティを指定します。ショートハンドで書くと「キーフレーム名 アニメーションにかかる時間 イージング 遅延時間 繰り返しの回数 再生方向」となります。「キーフレーム名」は必須ですし、再生秒数も書かないと0秒になるので指定します。div#sampleAnimeの設定は以下の通りです(分かり易くする為に、繰り返しの回数をinfiniteにしました)。
123456#sampleAnime {/* この記事を書いている時点ではベンダープレフィックスが必要 */-moz-animation:hogehoge 5s infinite;-webkit-animation:hogehoge 5s infinite;animation:hogehoge 5s infinite;} - キーフレームの書式は以下の通り。一つのkeyframesの中カッコの中に、各タイミングを現す n% をセレクタにした中カッコが入れ子になる構造です。
123456789101112131415@keyframes hogehoge {0% {margin-left: 10px;background-color: #f00;}20% {margin-left: 50px;}100% {margin-left: 50px;background-color: #ff0;}}
@keyframesで、注意すべき事が3つあります。- 各タイミングで指定しなかったプロパティは、変化が継続します。div#sampleAnimeでは、margin-leftは0→20%で10pxから100pxへとアニメーションし、20%→100%では変化しません。20%の時にbackground-colorを書いていないので、background-colorは0→100%にかけて色が変化します。
- この記事を書いている時点では、@keyframesにもベンダープレフィックスをつけたものを用意する必要があります。@-moz-keyframes hogehoge{}、@keyframes hogehoge{}、@keyframes hogehoge{}を用意すれば良いでしょう。animation-nameは同じで大丈夫です。
- この記事を書いている時点では、linear-gradientをanimationすることはできません。また、:afterや:beforeで作った疑似要素はFirefoxならanimationできますが、SafariやChromeではanimationできません。
スライドショーの@keyframes
各スライドの共通の動作は以下の順で行うことにします。
- 右からフレームイン
- ちょっと止まる
- 左へフレームアウト
お手本の@keyframesでは、各スライド毎に別のルールを設定していますが、工夫すれば1つの@keyframesで実装できます。
動作が分かりやすい様に、完成時に表示したいエリアのdiv.maskを追加して、赤いボーダーをつけた状態でアニメーションを表示してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
/*ベンダープレフィックスは省略しています。*/ .anime.loop .mask li { position:absolute; top:0; left:100%; /*フレーム「イン」させたいので、left:100%で右側の外に待機*/ animation:slide 12s 0s infinite; /*まず、各スライドに同じ@keyframesで動く様に指示*/ animation-play-state:running; /*webkitの動作が怪しいので追加。*/ } .anime.loop .mask li:nth-of-type(1) { animation-delay:0s;/* 1番目のスライドはすぐにスタート */ } .anime.loop .mask li:nth-of-type(2) { animation-delay:4s;/* 2番目のスライドは4秒後にスタート */ } .anime.loop .mask li:nth-of-type(3) { animation-delay:8s;/* 3番目のスライドは8秒後にスタート */ } /*以下が@keyframes*/ @keyframes slide { 0% {left:100%;opacity:0.5;z-index:10;} /*フレームイン開始*/ 10% {left:0%;opacity:1;} /*(a)全体の1/10秒でフレームイン終了*/ 33.3% {left:0%;opacity:1;z-index:-10;} /*(b)ここまで停止して、フレームアウト開始(b = 100 / スライド数) */ 43.3% {left:-100%;top:0%;opacity:0.5;} /*(c)フレームアウト終了(c = a) */ 50% {left:-100%;top:100%;} /* 分かりやすい様に、見えないエリアで迂回させています */ 70% {left:100%;top:100%;} 80% {left:100%;top:0%;} } |
- まず、各スライドに同じ@keyframesで動く様に指定
- その後で遅延時間のanimation-delayだけを個別に変更
一つの@keyframesと、スライド毎のdelayで、全てのスライドの動きを処理しているのが、この設定のミソです。
-moz-と-webkit-のベンダープレフィックス付き@keyframesを用意しても3つで済みます。
以下の計算式で任意のスライド枚数のanimation-delayを求めることができます。
hoverしたらanimationを一時停止させる
animation-play-stateを各<li>のhoverに設定すると、そのスライドのアニメは止まりますが、他のスライドは動き続けます。
1 2 3 4 5 |
/*SAMPLE LI:hover*/ /*これではアニメーションがずれてしまう...*/ .anime.loop.sample6 .mask li:hover{ animation-play-state:paused; } |
これでは、hoverの後でアニメがずれてしまうので、どのスライドにhoverしても、全てのアニメーションが止まる様にしなければなりません。そこで、セレクターにちょっとした工夫をします。SAMPLE LI:hoverと以下のSAMPPLE MASK:hoverにマウスをのせて、動作を比較しましょう。
1 2 3 4 5 |
/*SAMPLE MASK:hoverの工夫*/ /*セレクターを「liの親のhoverの子のli」にするのがポイント*/ .anime.loop.paused .mask:hover li{ animation-play-state:paused; } |
div.progress-barにもanimationを設定する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
.progress .progress-bar { background:rgba(0,0,0,1); height:5px; width:100%; position:absolute; z-index:100; bottom:0; left:0; -moz-animation:bar 12s linear infinite; -webkit-animation:bar 12s linear infinite; animation:bar 12s linear infinite; } @keyframes bar { 0%,43.3%,76.6% {width:0;opacity:0;} /*スライドのフレームイン中は表示しない */ 10%,53.3%,86.6% {width:10%;opacity:0.5;}/*フレームイン終了。ここからbarがのびる */ 30%,63.3%,96.6% {opacity:1;} /*barがのびきる前にopacityを1にするとおしゃれ */ 33.3%,66.6%,99.9% {width:100%;opacity:0.1;}/*ここまではbarがのびる */ 34%,67%,100% {width:100%;opacity:0;} /*barを消す */ } .progress .mask:hover .progress-bar{ animation-play-state:paused; bottom:-10px; } |
.progress-bar の@keyframesでは、お手本の@keyframesに習って、keyframeの%を、列挙する形でセレクタ指定してみました。スマートなやり方ですね。
また、hover時に、.progress-barもスライドと同様に一時停止しておきます。
表示させるエリアだけを見せて、他を隠す
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
#complete .mask { margin:0 auto; width:150px; height:150px; position:relative; cursor:pointer; overflow:hidden; } #complete ul{ list-style:none; height:150px; width:150px; margin: 0; padding: 0; position:relative; } #complete li { margin:0; padding: 0; height:150px; width:150px; top:0; left:100%; position:absolute; overflow:hidden; -moz-animation:slide 12s 0s infinite; -webkit-animation:slide 12s 0s infinite; animation:slide 12s 0s infinite; -moz-animation-play-state:running; -webkit-animation-play-state:running; animation-play-state:running; } #complete li:nth-of-type(1) { -moz-animation-delay:0s; -webkit-animation-delay:0s; animation-delay:0s; } #complete li:nth-of-type(2) { -moz-animation-delay:4s; -webkit-animation-delay:4s; animation-delay:4s; } #complete li:nth-of-type(3) { -moz-animation-delay:8s; -webkit-animation-delay:8s; animation-delay:8s; } #complete a { height:150px; width:150px; display:block; } #complete h2 { position:absolute; padding:0.5em 1em; background:rgba(0,0,0,0.5); color:#fff; top:0; left:-110%; opacity:0; -moz-transition:0.5s; -webkit-transition:0.5s; transition:0.5s; } #complete .mask:hover h2 { left:0; opacity:1; } #complete .mask:hover .progress-bar, #complete .mask:hover li{ -moz-animation-play-state:paused; -webkit-animation-play-state:paused; animation-play-state:paused; } #complete .progress-bar { background:rgba(0,0,0,1); height:5px; width:100%; position:absolute; z-index:100; bottom:0; left:0; -moz-animation:bar 12s linear infinite; -webkit-animation:bar 12s linear infinite; animation:bar 12s linear infinite; } /* keyframes for slide */ @-moz-keyframes slide { 0% {left:100%;opacity:0.5;z-index:10;} /*フレームイン開始*/ 10% {left:0%;opacity:1;} /*(a)全体の1/10秒でフレームイン終了*/ 33.3% {left:0%;opacity:1;z-index:-10;} /*(b)ここまで停止して、フレームアウト開始(b = 100 / スライド数) */ 43.3% {left:-100%;top:0%;opacity:0.5;} /*(c)フレームアウト終了(c = a) */ 50% {left:-100%;top:100%;} /* 分かりやすい様に、見えないエリアで迂回させた */ 70% {left:100%;top:100%;} 80% {left:100%;top:0%;} } @-webkit-keyframes slide { 0% {left:100%;opacity:0.5;z-index:10;} /*フレームイン開始*/ 10% {left:0%;opacity:1;} /*(a)全体の1/10秒でフレームイン終了*/ 33.3% {left:0%;opacity:1;z-index:-10;} /*(b)ここまで停止して、フレームアウト開始(b = 100 / スライド数) */ 43.3% {left:-100%;top:0%;opacity:0.5;} /*(c)フレームアウト終了(c = a) */ 50% {left:-100%;top:100%;} /* 分かりやすい様に、見えないエリアで迂回させた */ 70% {left:100%;top:100%;} 80% {left:100%;top:0%;} } @keyframes slide { 0% {left:100%;opacity:0.5;z-index:10;} /*フレームイン開始*/ 10% {left:0%;opacity:1;} /*(a)全体の1/10秒でフレームイン終了*/ 33.3% {left:0%;opacity:1;z-index:-10;} /*(b)ここまで停止して、フレームアウト開始(b = 100 / スライド数) */ 43.3% {left:-100%;top:0%;opacity:0.5;} /*(c)フレームアウト終了(c = a) */ 50% {left:-100%;top:100%;} /* 分かりやすい様に、見えないエリアで迂回させた */ 70% {left:100%;top:100%;} 80% {left:100%;top:0%;} } /* keyframes for progress-bar */ @-moz-keyframes bar { 0%,43.3%,76.6% {width:0;opacity:0;} 10%,53.3%,86.6% {width:10%;opacity:0.5;} 30%,63.3%,96.6% {opacity:1;} 33.3%,66.6%,99.9% {width:100%;opacity:0.1;} 34%,67%,100% {width:100%;opacity:0;} } @-webkit-keyframes bar { 0%,43.3%,76.6% {width:0;opacity:0;} 10%,53.3%,86.6% {width:10%;opacity:0.5;} 30%,63.3%,96.6% {opacity:1;} 33.3%,66.6%,99.9% {width:100%;opacity:0.1;} 34%,67%,100% {width:100%;opacity:0;} } @keyframes bar { 0%,43.3%,76.6% {width:0;opacity:0;} /*スライドのフレームイン中は表示しない */ 10%,53.3%,86.6% {width:10%;opacity:0.5;}/*フレームイン終了。ここからbarがのびる */ 30%,63.3%,96.6% {opacity:1;} /*barがのびきる前にopacityを1にするとおしゃれ */ 33.3%,66.6%,99.9% {width:100%;opacity:0.1;}/*ここまではbarがのびる */ 34%,67%,100% {width:100%;opacity:0;} /*barを消す */ } |
仕上げに、.maskのoverflowをhiddenして完成です。
ここまで説明の為にclassを追加しながらcssを足し込んでいて、ちょっと判りづらい所もあったので、id=complete として整理し直したhtmlとcssにしました。ベンダープレフィックスも書いてあります。
まとめ
ちょっと疲れました
思った以上にボリュームのある内容になりました。しかし、ベンダープレフィックスがある為に記述量が増えてしまいがちな@keyframesについて、スライド個別に作成しないで良い事に気付けたのは収穫でした。
スライドショーの使い道
Web表現としては手垢がついた感もあるスライドショーですが、TOPページでお為ごかしに使っているだけでは勿体ないです。
画面上で動いている物に目がいくのは人間の性なので、注目を引く効果があるのはもちろんです。が、それだけではありません。
スライドショーは、ほんの少しのアイデアと工夫で、様々なバリエーションへ発展できる表現です。例えば…
- 最新情報をNews Ticker風に表示
- Twitterのつぶやきを電光掲示板風に表示
- CSS3のtransformでアニメーションさせてサイバー空間風に表現
- レトロな額縁の中で動かして懐かしの紙芝居を再現
- 高速にスライドを切り替えてパラパラ漫画風に
- ウィンドウ全体の背景画像かと思わせて、実は画面一杯の大きなスライドショー!
- etc…
仕上げの細部にこだわろう
動きの細部(スピード・イージング・フェード)の演出しだいで、がらりと印象が変わるのもスライドショーの面白さです。どんな演出がしたいのか、よく考えましょう。
- ゆっくりと大きな画像を動かしたり、クロスフェードさせれば、優雅な表現に。
- フレームインとフレームアウトをキビキビと動かして、力強いプレゼン的な説得力を持たせた表現に。
- 少しだけ行き過ぎたスライドをバウンドさせて戻したりして、人間臭さを出した表現に。
- 画面を分割して、別々のタイミングでスライドさせることで、海外ドラマ 24風の緊迫感を。
CSSスライドショーはスマートフォンに最適!(かな?)
スマートフォンやタブレット端末のブラウザは、CSS3に対応している前提で作成できるので、こうしたCSSでの演出に向いていると言えます。Flash非対応のデバイスだからjQueryで!と短絡する前に、CSSでも出来るようにしておく事で、選択肢が広がります。
興味とチャレンジ精神のある人は、是非、自分でCSSスライドショーを作ってみて下さい。3パターンくらいを作り終える頃には、css animationを自在に操れるようになるはずです。
ピンバック: 2012-9-21勉強会 | パソコン倶楽部りんご
寝る前に、ちょっとサイトを確認と思って、気軽に記事を見てびっくりしました。
気軽な内容じゃないですね!!!!時間のある時にしっかり見ます。
とりあえず、お疲れ様でした。
ピンバック: 2012-9-21勉強会 | パソコン倶楽部りんご
ピンバック: WordPressで複数ヘッダー画像をcssスライドショーで動かす | パソコン倶楽部りんご
.htmlありませんか?
なんかlist縦並びなんですけど
説明はわかりやすいのですが、cssを追加していった時にhtmlのclass名なども変化しててそこも一緒に伝えてくれないとわかりづらいです。
sample1から2の横並びにするだけで既にわかりづらくてびっくりしました。