サムネイル表示にも対応! CSSだけで作るスライドショー その②
この記事の目次
サムネイル付きスライドショー
以前まとめた記事を応用して、スライドショーを改良してみました。
自動で繰り返すし、サムネイルをクリックして画像を切り替えられるようにしてあります
まずはデモから
サムネイルクリックで切り替わります
ラジオボタンを埋め込んだHTMLを作成する
今回のキモは画像を切り替えるためにラジオボタンを使うところにあります
まずはHTMLのサンプルコードから
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<div> <input type="radio" name="photo" id="img1" checked> <input type="radio" name="photo" id="img2"> <input type="radio" name="photo" id="img3"> <div class="slide"> <img src="img/img1.jpg" alt=""> <img src="img/img2.jpg" alt=""> <img src="img/img3.jpg" alt=""> </div> <ul class="thumbnail"> <li> <label for="img1"> <img src="img/img1.jpg" alt=""></label> </li> <li> <label for="img2"> <img src="img/img2.jpg" alt=""></label> </li> <li> <label for="img3"> <img src="img/img3.jpg" alt=""></label> </li> </ul> </div> |
邪魔にならない場所にラジオボタンを画像分用意
離れた場所に設置したサムネイルをクリックしたときにチェックできるようにするので、ID属性を必ずつける
あらかじめ一枚目に対応したものはchecked属性を付けて選択済みに
表示はCSSの方で消しますが調整中は表示したままのほうがやりやすいと思われる
画像は一つのグループにしておく
今回はdiv要素にしています
サムネイル画像を用意する
サムネイルはlabel要素で囲み、for属性を使って離れた場所に設置したラジオボタンと関連付けする
箇条書きリストとして今回はマークアップしました
見栄えは悪いですがページ上部にラジオボタンが設置されますのでサムネイルクリックでラジオボタンが切り替わることを確認しておきましょう
CSSを書く
CSSに関しては@keyframesとanimationプロパティを軸に設定していきます
他にも細かい調整をしながらコードを書いていきます。
※説明なんかいらねーからコピペさせろという方は自力でスクロールしてください
ラジオボタンを非表示にする
調整中は表示しておいたほうがやりやすいかもですが、消しておきます
単純にdisplayプロパティを使って消してしまいましょう
1 2 3 |
input[type="radio"]{ display: none; } |
ここでは簡単なセレクタの指定方法にしていますが、フォーム等を使っている場合は親要素も絡めて指定してください
画像を一か所に重ねる
スライドショーをクロスフェードで作りますのであらかじめ重ね合わせておきます
positionプロパティなどを使うとやりやすいかもしれません
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.slide { position: relative; width: 100%; height: 500px; overflow: hidden; } .slide img { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 100%; height: auto; opacity: 0; } |
サムネイルの設定
特別難しいことはないですが、横並びにしつつマウスカーソルの表示を変えています
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.thumbnail { list-style: none; display: flex; padding: 0; margin-top: 30px; justify-content: center; } .thumbnail img { display: block; width: 200px; height: 100px; object-fit: cover; margin: 10px; cursor: pointer; } |
@keyframesでアニメーションを用意する
以前の記事で紹介したものと同じアニメーションを使えますので流用します
詳しいことは以前の記事をご覧ください
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 |
/*自動でサムネイルを切り替えるアニメーション*/ @keyframes thumb1 { 0% { filter: grayscale(0%); } 6% { filter: grayscale(100%); } 10% { filter: grayscale(100%); } 28% { filter: grayscale(100%); } 37% { filter: grayscale(0%); } 100% { filter: grayscale(0%); } } /*スライドショー用アニメーション*/ @keyframes slideshow1 { 0% { opacity: 0; } 10% { opacity: 1; } 28% { opacity: 1; } 38% { opacity: 0; } 100% { opacity: 0; } } |
今回のコードではサムネイルのクリックでアニメーションを切り替えます。
同じアニメーションを画像と同じ分用意しておくと動きが安定しますので簡単に番号付きで3つ用意しましょう
アニメーションを実行する
animationプロパティでアニメーションを実行していきます。
今回はどのラジオボタンにチェックが入っているかによって動きを変えていくので
「checked疑似クラス」を使ってそれぞれの状況に対応していきます。
まずはページを開いた状態から
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 |
/*ページを開いたとき&一つ目のサムネイルをクリックしたとき*/ #img1:checked ~ .thumbnail label[for="img1"] img { animation: thumb1 24s linear infinite both; animation-delay: 0s; cursor: auto; } #img1:checked ~ .thumbnail label[for="img2"] img { animation: thumb1 24s linear infinite both; animation-delay: 8s; } #img1:checked ~ .thumbnail label[for="img3"] img { animation: thumb1 24s linear infinite both; animation-delay: 16s; } #img1:checked ~ .slide img { animation: slideshow1 24s linear infinite; } #img1:checked ~ .slide img:nth-child(1) { animation-delay: 0s; } #img1:checked ~ .slide img:nth-child(2) { animation-delay: 8s; } #img1:checked ~ .slide img:nth-child(3) { animation-delay: 16s; } |
要素の後ろにある同じ階層のセレクタの指定指定するため「#img1:checked ~ 同一階層の要素 子要素」の形をとっています。
後はそれぞれの状況によってアニメーションを変えてあげればおしまい
まるっとコピペ用コード
状況によってコードを変える必要もありますし、好みによって微調整をしないといけませんがCSSを丸ごと貼っておきます
上のほうにあるHTMLと組み合わせて試しながら調整してください
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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
.slide { position: relative; width: 100%; height: 500px; overflow: hidden; } .slide img { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 100%; height: auto; opacity: 0; } @keyframes thumb1 { 0% { filter: grayscale(0%); } 6% { filter: grayscale(100%); } 10% { filter: grayscale(100%); } 28% { filter: grayscale(100%); } 37% { filter: grayscale(0%); } 100% { filter: grayscale(0%); } } @keyframes thumb2 { 0% { filter: grayscale(0%); } 6% { filter: grayscale(100%); } 10% { filter: grayscale(100%); } 28% { filter: grayscale(100%); } 37% { filter: grayscale(0%); } 100% { filter: grayscale(0%); } } @keyframes thumb3 { 0% { filter: grayscale(0%); } 6% { filter: grayscale(100%); } 10% { filter: grayscale(100%); } 28% { filter: grayscale(100%); } 37% { filter: grayscale(0%); } 100% { filter: grayscale(0%); } } @keyframes slideshow1 { 0% { opacity: 0; } 10% { opacity: 1; } 28% { opacity: 1; } 38% { opacity: 0; } 100% { opacity: 0; } } @keyframes slideshow2 { 0% { opacity: 0; } 10% { opacity: 1; } 28% { opacity: 1; } 38% { opacity: 0; } 100% { opacity: 0; } } @keyframes slideshow3 { 0% { opacity: 0; } 10% { opacity: 1; } 28% { opacity: 1; } 38% { opacity: 0; } 100% { opacity: 0; } } .thumbnail { list-style: none; display: flex; padding: 0; margin-top: 30px; justify-content: center; } input[type="radio"] { display: none; } .thumbnail img { display: block; width: 200px; height: 100px; object-fit: cover; margin: 10px; cursor: pointer; } /*ページを開いたとき&一つ目のサムネイルをクリックしたとき*/ #img1:checked ~ .thumbnail label[for="img1"] img { animation: thumb1 24s linear infinite both; animation-delay: 0s; cursor: auto; } #img1:checked ~ .thumbnail label[for="img2"] img { animation: thumb1 24s linear infinite both; animation-delay: 8s; } #img1:checked ~ .thumbnail label[for="img3"] img { animation: thumb1 24s linear infinite both; animation-delay: 16s; } #img1:checked ~ .slide img { animation: slideshow1 24s linear infinite; } #img1:checked ~ .slide img:nth-child(1) { animation-delay: 0s; } #img1:checked ~ .slide img:nth-child(2) { animation-delay: 8s; } #img1:checked ~ .slide img:nth-child(3) { animation-delay: 16s; } /*二つ目のサムネイルをクリックしたとき*/ #img2:checked ~ .thumbnail label[for="img1"] img { animation: thumb2 24s linear infinite both; animation-delay: 16s; } #img2:checked ~ .thumbnail label[for="img2"] img { animation: thumb2 24s linear infinite both; animation-delay: 0s; cursor: auto; } #img2:checked ~ .thumbnail label[for="img3"] img { animation: thumb2 24s linear infinite both; animation-delay: 8s; } #img2:checked ~ .slide img { animation: slideshow2 24s linear infinite; } #img2:checked ~ .slide img:nth-child(1) { animation-delay: 16s; } #img2:checked ~ .slide img:nth-child(2) { animation-delay: 0s; } #img2:checked ~ .slide img:nth-child(3) { animation-delay: 8s; } /*二つ目のサムネイルをクリックしたとき*/ #img3:checked ~ .thumbnail label[for="img1"] img { animation: thumb3 24s linear infinite both; animation-delay: 8s; } #img3:checked ~ .thumbnail label[for="img2"] img { animation: thumb3 24s linear infinite both; animation-delay: 16s; } #img3:checked ~ .thumbnail label[for="img3"] img { animation: thumb3 24s linear infinite both; animation-delay: 0s; cursor: auto; } #img3:checked ~ .slide img { animation: slideshow3 24s linear infinite; animation-delay: 8s; } #img3:checked ~ .slide img:nth-child(1) { animation-delay: 8s; } #img3:checked ~ .slide img:nth-child(2) { animation-delay: 16s; } #img3:checked ~ .slide img:nth-child(3) { animation-delay: 0s; } |