HTML&CSS
HTMLとCSSのみでWebサイト用のスライドショーを作る/ボタン付きの場合の解説も
ズームイン、ズームアウトしながら画像が切り替わるスライドショーと、流れるスライドショーについて、jQueryなどのライブラリはおろかJavaScriptなしで作る方法についてご紹介します。
一気に説明せず、ひとつひとつの要素に分けてご説明していきます。
HTMLとCSSだけで画像が切り替わるスライドショー
(1)基本形
次のようなスライドショーをCSSだけで作成できます。
ソースコード
HTML
<style><div class="img-frame">
<div class="img-01"></div>
<div class="img-02"></div>
<div class="img-03"></div>
</div>
CSS
.img-frame{
position: relative;
width: 70%;
height: 300px;
overflow: hidden;
margin: 0 auto;
}
@media screen and (max-width: 767px){
.img-frame{
width: 100%;
height: 200px;
}
.img-01, .img-02, .img-03{
position: absolute;
top:0;
left:0;
width: 100%;
height: 100%;
background-size: cover;
background-repeat: no-repeat;
}
.img-01{
background-image: url('画像の場所');
animation: slide-animation-01 24s infinite;
}
.img-02{
background-image: url('画像の場所');
animation: slide-animation-02 24s infinite;
}
.img-03{
background-image: url('画像の場所');
animation: slide-animation-03 24s infinite;
}
@keyframes slide-animation-01 {
0% {opacity: 1; transform: scale(1.0);}
30% {opacity: 1;}
40% {opacity: 0; transform: scale(1.15);}
90% {opacity: 0}
100% {opacity: 1; transform: scale(1.0);}
}
@keyframes slide-animation-02 {
0% {opacity: 0;}
30% {opacity: 0; transform: scale(1.1);}
40% {opacity: 1;}
60% {opacity: 1;}
70% {opacity: 0; transform: scale(1.0);}
100% {opacity: 0;}
}
@keyframes slide-animation-03 {
0% {opacity: 0;}
60% {opacity: 0; transform: scale(1.0);}
70% {opacity: 1;}
90% {opacity: 1;}
100% {opacity: 0; transform: scale(1.1);}
}
解説
以下、CSSセレクタで対象要素を説明します。
.img-frame
で外枠を作っています。外枠の大きさをwidth: 70%
、height: 300px
としていますが、そこは好きな大きさにできるところです。- 画像3枚は
.img-01
、.img-02
、.img-03
のそれぞれに背景画像として指定しています。ここはimg
要素を使って普通に画像にしても実現可能なのですが、背景画像にした方がカスタマイズ性が高くできます。どのようにカスタマイズ性が違うのかは後述します。 .img-frame
にoverflow: hidden
を指定して、内枠の背景画像がはみ出した分を非表示にします。.img-01
、.img-02
、.img-03
はそれぞれ、position: absolute
として、外枠に対して同じ位置で表示されるようにします。.img-01
、.img-02
、.img-03
それぞれに同じ時間(この例では24秒間ですが、好きな長さに設定可能)のanimation
をつけています。3枚それぞれをCSSのanimation
で、拡大縮小、透明度の変化をつけることでこのスライドショーが実現できます。
(2)上に半透明の矩形を重ねる
次のように上に半透明の矩形を乗せることもCSSで可能です。
ソースコード
先ほどの(1)のCSSに対して、以下の追記をすればこうなります。
CSS
.img-frame::after{
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
}
解説
外枠に疑似要素を指定して、position: absolute;
で外枠と同じ位置に半透明の矩形を乗せています。
(3)テキストを乗せる
次のようなこともCSSだけでできます。
京都
横浜
良い街
ソースコード
(1)のHTMLを次のように変え、疑似要素で付けている半透明の上に乗せた矩形は、外枠ではなく.img-03
につける形に変更です。それ以外のCSSは(1)に対する追記です。
HTML
<div class="img-frame">
<div class="img-01"><p class="msg msg-01">京都</p></div>
<div class="img-02"><p class="msg msg-02">横浜</p></div>
<div class="img-03 cover"><p class="msg msg-03">良い街</p></div>
</div>
CSS
.msg{
font-size: 20px;
color: #fff;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% , -50%);
}
.msg-01, .msg-02{
text-shadow: 2px 2px 3px #000, -1px -1px 3px #000;
}
.img-03.cover::after{
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .7);
}
.msg-03{
z-index:1;
}
解説
半透明の矩形を外枠に対してつけるのではなく、内枠の背景画像の3番目に対して付けてます。
テキストの位置は、position: absolute;
で外枠に対して中央に配置しています。
(4)角丸をつける、画像の大きさを変える
京都
横浜
良い街
ソースコード
(3)のソースコードのCSSに以下の変更/追記をするだけです。
CSS
.img-frame{
width: 100%;
height: 200px;
clip-path: inset(0 round 0 0 0 50px);
}
解説
外枠のwidth
を70%から100%に、height
を300pxから200pxに変えています。
また、外枠にclip-path
で角丸をつけています。
こういうのが、img要素ではなく背景画像を使ったときにカスタマイズ性が高くなるところです。
角丸はborder-radiusでも同様に外枠に対して指定すれば付けられるのですが、border-radiusだとiOSでは現時点、つきません。なので、clip-pathにしています。
こういうの最近多いですね、Appleさん。
(5)画像の表示位置を変える
スマホだと調整が大変なので、ここではPCでだけ変わるようにしています。PCで違いをご確認ください。
京都
横浜
良い街
ソースコード
(4)のソースコードのCSSに以下の追記をするだけです。上述の通り、ここではあえてPCでだけ変わるようにしています。
CSS
@media screen and (min-width:768px){
.img-01{
background-position: 0 -250px;
}
.img-02{
background-position: 0 -200px;
}
.img-03{
background-position: 0 -200px;
}
}
解説
背景画像の位置はbackground-position
で変更できるので、それを利用しています。
これもimage
要素を使うとできないことです。image
要素を使った場合はtransform
プロパティを使ってトライすることになると思うんですが、思うようにいかないと思います(私はそうでした)。
これも注意点があって、iOSとAndroidで大きく表示位置が異なります・・なので、ここまでカスタマイズしようと思うと、ちょっと検証が大変ではあります。
HTMLとCSSだけで画像が流れるスライドショー
縦に流れるスライドショー
次のような流れるスライドショーもCSSだけでできてしまいます。
ソースコード
HTML
<div class="slide-container">
<div class="slide-wrapper">
<img class="slide" src="画像の場所" alt="京都">
<img class="slide" src="画像の場所" alt="横浜">
<img class="slide" src="画像の場所" alt="良い街">
</div>
<div class="slide-wrapper">
<img class="slide" src="画像の場所" alt="京都">
<img class="slide" src="画像の場所" alt="横浜">
<img class="slide" src="画像の場所" alt="良い街">
</div>
<div class="slide-wrapper">
<img class="slide" src="画像の場所" alt="京都">
<img class="slide" src="画像の場所" alt="横浜">
<img class="slide" src="画像の場所" alt="良い街">
</div>
</div>
CSS
.slide-container {
width: 700px;
display: flex;
align-items: center;
height: 340px;
overflow: hidden;
flex-direction: column;
}
.slide-wrapper {
display: flex;
flex-direction: column;
animation: slide-flow 20s infinite linear 1s both;
}
.slide{
width: 300px;
object-fit: cover;
border: 1px solid #ddd;
}
@keyframes slide-flow {
0% {transform: translateY(0);}
100% {transform: translateY(-100%);}
}
解説
外枠をoverflow: hidden;
にしてはみ出す部分を表示させないようにし、3×3で9枚の画像をループさせて3枚の画像だけがループしているように見せるという方法です。
横に流れるスライドショー
上述のCSSの中で.slide-container
と.slide-wrapper
につけているflex-direction: column;
を削り(flex-direciton: row;
にする)、animationの最終地点のところをtransform: translateY(-100%);
からtransform: translateX(-100%);
にすれば、横に流れる形になります。
スライド全体の幅は、.slide-container
のwidth
で指定します。
.slide-container {
width: 100%;
margin: 50px auto;
display: flex;
align-items: center;
overflow: hidden;
}
.slide-wrapper {
display: flex;
animation: slide-flow 20s infinite linear 1s both;
}
.slide{
width: 300px;
object-fit:cover;
border: 1px solid #ddd;
}
@keyframes slide-flow {
0% {transform: translateX(0);}
100% {transform: translateX(-100%);}
}
マウスオーバー(ホバー)時に止める
.slide-container
に.slide-paused
(名称は自由)などとクラス名を付与し、ホバー時に
animation-play-state: paused;
を指定することで、マウスオーバー(ホバー)時に動きを止めることができます。
ontouchstart=""
はスマホのタップ時の挙動を決めるための記述です。
.slide-paused:hover .slide-wrapper img:hover
へのopacityとcursorの指定は、動きを止める部分ではなく、見た目の変更です。なくても動きは止まります。
HTML
<div class="slide-container slide-paused" ontouchstart="">
</div>
CSS
.slide-paused:hover .slide-wrapper {
animation-play-state: paused;
}
.slide-paused:hover .slide-wrapper img:hover {
opacity: .8;
cursor: grabbing;
}
スライドショーにボタンを付ける場合
ボタンを付けるには
本記事は最初は「スライドショーをCSSのみ(JavaScriptなし)で作る」でしたが、それなのに何故か「ボタン付き」の検索キーワードでも上位に表示されていて、それで見ていただいている方も多いようなので、いっそのことタイトルに「ボタン付き」と加えて解説することにしました。
クリックで動作させる場合の動作内容について、画面遷移とそうでないものとに分けた場合に、前者はa要素を用いればJavaScriptなしで動作するものの、後者は現状、JavaScriptを用いるしかありません。
addEventListener()
のメソッドを用います。
対象要素.addEventListener( 種類, 関数, false )
のように記述するもので、種類のところを’click’とすれば、対象要素をクリックしたときの動作を決めることができます。
スライドショーを1枚ずつ動かすボタンを付ける場合、ここでご紹介したCSSでの実装方法だと、JavaScriptを用いたとしても難しいので、それであれば最初からJavaScriptで実装するということになります。そうなってくるとそもそも、JavaScriptのライブラリを使った方法が良いと思います。
ニーズがあるかは分かりませんが、スライドショーの動きの停止、再生は、ここでご紹介したCSSによる実装をベースに、JavaScriptで簡単に実装可能です。
ソースコード
HTML
<div class="slider-wrapper">
<div class="slide-container">
<div class="slide-wrapper">
<img class="slide" src="画像の場所" alt="京都">
<img class="slide" src="画像の場所" alt="横浜">
<img class="slide" src="画像の場所" alt="良い街">
</div>
<div class="slide-wrapper">
<img class="slide" src="画像の場所" alt="京都">
<img class="slide" src="画像の場所" alt="横浜">
<img class="slide" src="画像の場所" alt="良い街">
</div>
<div class="slide-wrapper">
<img class="slide" src="画像の場所" alt="京都">
<img class="slide" src="画像の場所" alt="横浜">
<img class="slide" src="画像の場所" alt="良い街">
</div>
</div>
<div class="btns-wrapper">
<button id="stopBtn" class="slider-btn">STOP</button>
<button id="startBtn" class="slider-btn">START</button>
</div>
</div>
JavaScript
const stopBtn = document.getElementById('stopBtn')
const startBtn = document.getElementById('startBtn')
const sliders = document.querySelectorAll('.slide-wrapper')
stopBtn.addEventListener('click', function() {
sliders.forEach( function(slider){
slider.style.animation = 'none';
});
}, false);
startBtn.addEventListener('click', function() {
sliders.forEach( function(slider){
slider.style.animation = 'slide-flow 20s infinite linear 1s both';
});
}, false);
まとめ
CSSだけでスライドショー作れちゃうよシリーズでした。
ライブラリを使った方が実装は早いというケースももちろんあるとは思いますが、基本的にはJavaScriptを使うよりCSSのみの方が処理速度が速いと思います。また、ライブラリだと何か思ったように動かないというときに、環境のバグなのかカスタマイズの仕方が悪いのかの特定が難しくなりますし、ちゃんと動きの理屈を理解したコードの方が思ったようにいきやすかったりすると思います。