Weblasts

サムネイル表示にも対応! CSSだけで作るスライドショー その②

サムネイル付きスライドショー

以前まとめた記事を応用して、スライドショーを改良してみました。
自動で繰り返すし、サムネイルをクリックして画像を切り替えられるようにしてあります

まずはデモから
サムネイルクリックで切り替わります

SAMPLE

ラジオボタンを埋め込んだHTMLを作成する

今回のキモは画像を切り替えるためにラジオボタンを使うところにあります
まずはHTMLのサンプルコードから

HTML

<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プロパティを使って消してしまいましょう

CSS

input[type="radio"]{
  display: none;
}

ここでは簡単なセレクタの指定方法にしていますが、フォーム等を使っている場合は親要素も絡めて指定してください

画像を一か所に重ねる

スライドショーをクロスフェードで作りますのであらかじめ重ね合わせておきます
positionプロパティなどを使うとやりやすいかもしれません

CSS

.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;
}

サムネイルの設定

特別難しいことはないですが、横並びにしつつマウスカーソルの表示を変えています

CSS

.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でアニメーションを用意する

以前の記事で紹介したものと同じアニメーションを使えますので流用します
詳しいことは以前の記事をご覧ください

CSS

/*自動でサムネイルを切り替えるアニメーション*/
@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疑似クラス」を使ってそれぞれの状況に対応していきます。
まずはページを開いた状態から

CSS

/*ページを開いたとき&一つ目のサムネイルをクリックしたとき*/
#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と組み合わせて試しながら調整してください

CSS

.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;
}

Recommend Post