HTMLとCSSだけで「止まらない」美しいスライドショーを作る完全ガイドJavaScript最小で運用できる設計と、停止・再生ボタンまでの拡張

スマホ主流のいま、トップのヒーローエリアやロゴスライダーはサイトの第一印象を決める重要パーツです。ところが、ライブラリに頼りすぎると読み込みサイズの増加、バージョン差異による不具合、カスタマイズの難しさに悩みがち。そこで本稿では、「HTMLとCSSのみでWebサイト用のスライドショーを作る(ボタン付きの解説あり)」という良質な解説を出発点に、実務で使える設計・コード・落とし穴回避・アクセシビリティ配慮までを体系化しました。基礎はCSSだけで、必要最小限のJavaScriptで停止・再生ボタンを追加する方針です(元記事の構成と趣旨) 。


目次

  1. なぜCSSだけで作るのか:実務メリット
  2. 「フェード+ズーム」3枚スライドの基本構成
  3. 意匠の拡張:半透明オーバーレイ、テキストの合成、角丸やクリッピング
  4. 「流れる」スライドの実装:縦スクロール型と横スクロール型
  5. ホバーで一時停止、タップ環境への配慮
  6. 停止・再生ボタンの追加(最小JS)
  7. 実務の落とし穴:iOSとAndroidの表示差/背景位置とオブジェクトフィット
  8. パフォーマンスとアクセシビリティ設計
  9. 運用指針:デザインシステムへの落とし込み
  10. コピペで使えるテンプレート集
  11. まとめ:CSSファーストで軽く、美しく、壊れにくく
  12. さらに深く学ぶための参考

1. なぜCSSだけで作るのか:実務メリット

  • 読み込みの軽さ:ライブラリ分のJSを持たないため初期描画が軽く、CLSも安定しやすい。
  • 可読性と可搬性:アニメーションの理屈がCSSで透明化され、保守が容易。バグ原因の切り分けもしやすい(環境/バージョンの影響を受けにくい) 。
  • 装飾の自由度:背景画像を用いることで、切り抜き、角丸、クリッピング、重ね表現などが自在になる(後述のclip-path活用など) 。

2. 「フェード+ズーム」3枚スライドの基本構成

HTML骨格

<div class="img-frame">
  <div class="img-01"></div>
  <div class="img-02"></div>
  <div class="img-03"></div>
</div>

CSSの要点

  • 外枠はposition: relative; overflow: hidden;でトリミング。
  • 各スライドはposition: absolute; inset: 0; background-size: cover;で全面配置。
  • @keyframesで不透明度と拡大率を時間差で制御し、3枚が順番に現れて消える。
.img-frame {
  position: relative;
  width: 70%;
  height: 300px;
  overflow: hidden;
  margin: 0 auto;
}
.img-01, .img-02, .img-03 {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-repeat: no-repeat;
}
.img-01 { background-image: url('1.jpg'); animation: slide-01 24s infinite; }
.img-02 { background-image: url('2.jpg'); animation: slide-02 24s infinite; }
.img-03 { background-image: url('3.jpg'); animation: slide-03 24s infinite; }

@keyframes slide-01 {
  0% {opacity: 1; transform: scale(1);}
  30% {opacity: 1;}
  40% {opacity: 0; transform: scale(1.15);}
  90% {opacity: 0;}
  100% {opacity: 1; transform: scale(1);}
}
@keyframes slide-02 {
  0% {opacity: 0;}
  30% {opacity: 0; transform: scale(1.1);}
  40% {opacity: 1;}
  60% {opacity: 1;}
  70% {opacity: 0; transform: scale(1);}
  100% {opacity: 0;}
}
@keyframes slide-03 {
  0% {opacity: 0;}
  60% {opacity: 0; transform: scale(1);}
  70% {opacity: 1;}
  90% {opacity: 1;}
  100% {opacity: 0; transform: scale(1.1);}
}

ポイント:3枚とも同一時間(例: 24s)でループし、各キーフレームで出番の時間帯をずらすのがコツ。元記事の基本構成を踏襲しています 。


3. 意匠の拡張:半透明オーバーレイ、テキストの合成、角丸やクリッピング

3-1. 半透明オーバーレイで視認性を担保

.img-frame::after {
  content: "";
  position: absolute; inset: 0;
  background-color: rgba(0,0,0,.5);
}

画像の上に暗幕を敷くことでテキストやCTAの可読性を高める(元記事の拡張例) 。

3-2. スライド上にテキストを載せる

<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>
.msg {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%,-50%);
  color: #fff; font-size: 20px;
}
.img-03.cover::after {
  content:""; position: absolute; inset: 0;
  background: rgba(0,0,0,.7);
}

「3枚目だけ暗幕を濃くして上にテキスト」などの演出もCSSのみで実現できます 。

3-3. 角丸を大胆に:

clip-path

の採用

.img-frame {
  width: 100%;
  height: 200px;
  /* iOSでのborder-radiusの制約を回避して角丸表現 */
  clip-path: inset(0 round 0 0 0 50px);
}

iOSでborder-radiusが効きにくいケースがあるため、**確実に角丸を出したい場合はclip-path**が有力(元記事の指摘) 。


4. 「流れる」スライドの実装:縦スクロール型と横スクロール型

4-1. 縦に流れるスライド(カラムをアニメーション)

<div class="slide-container">
  <div class="slide-wrapper">
    <img class="slide" src="1.jpg" alt="京都">
    <img class="slide" src="2.jpg" alt="横浜">
    <img class="slide" src="3.jpg" alt="良い街">
  </div>
  <div class="slide-wrapper">…同じ内容…</div>
  <div class="slide-wrapper">…同じ内容…</div>
</div>
.slide-container {
  width: 700px; height: 340px;
  display: flex; flex-direction: column;
  align-items: center; overflow: hidden;
}
.slide-wrapper {
  display: flex; flex-direction: column;
  animation: slide-flow 20s linear 1s both infinite;
}
.slide { width: 300px; object-fit: cover; border: 1px solid #ddd; }
@keyframes slide-flow {
  0%   { transform: translateY(0); }
  100% { transform: translateY(-100%); }
}

3列×3枚=9枚を循環させ、3枚だけループしているように見せるテクニックが肝です(元記事の考え方) 。

4-2. 横に流れるスライド(行をアニメーション)

縦の例からflex-directionをrowに、translateYをtranslateXに変更するだけで横流しに変換できます。可読性のためwidth: 100%にして横幅一杯で見せるのも定番 。


5. ホバーで一時停止、タップ環境への配慮

<div class="slide-container slide-paused" ontouchstart="">
  …
</div>
.slide-paused:hover .slide-wrapper {
  animation-play-state: paused;
}
.slide-paused:hover .slide-wrapper img:hover {
  opacity: .8; cursor: grabbing; /* 見た目の演出(任意) */
}

PCではホバー時に停止させるのが自然。スマホはホバーがないため、後述のボタンで制御するのが確実です(元記事のガイド) 。


6. 停止・再生ボタンの追加(最小JS)

CSSベースを崩さず、再生・停止だけJSで行うミニマル設計。

<div class="slider-wrapper">
  <div class="slide-container">…(縦または横の例)…</div>
  <div class="btns-wrapper">
    <button id="stopBtn"  class="slider-btn">STOP</button>
    <button id="startBtn" class="slider-btn">START</button>
  </div>
</div>
<script>
const stopBtn  = document.getElementById('stopBtn');
const startBtn = document.getElementById('startBtn');
const sliders  = document.querySelectorAll('.slide-wrapper');

stopBtn.addEventListener('click', () => {
  sliders.forEach(slider => slider.style.animation = 'none');
}, false);

startBtn.addEventListener('click', () => {
  sliders.forEach(slider => slider.style.animation = 'slide-flow 20s infinite linear 1s both');
}, false);
</script>
  • ボタンでアニメーションの付け外しを行うため、JSの責務は最小限。
  • 「1枚ずつ進める」「戻る」を求めるなら、最初からJSでスライダー実装に切り替えた方が良い(元記事の結論と同じ方針) 。

7. 実務の落とし穴:iOSとAndroidの表示差/背景位置とオブジェクトフィット

  • 背景の見え方差:background-positionはOS/ブラウザ差で体感のズレが出やすい。PCだけで位置を変えるなど、調整の工数を読んでおくと良い(元記事でも「大きく表示位置が異なる」旨の注意) 。
  • border-radiusと角丸:iOSで効きにくいケースへの対処としてclip-pathを使う(前述) 。
  • object-fitbackground-size:imgならobject-fit: cover;、背景ならbackground-size: cover;でトリミング結果を揃える。画像と背景で調整手段が変わる点に留意(元記事の「背景画像採用でカスタマイズ性が高い」趣旨) 。

8. パフォーマンスとアクセシビリティ設計

  • パフォーマンス:CSSアニメーションは軽量で理解しやすく、ライブラリ障害に巻き込まれにくい。ただし多枚数・大きな画像では転送量がボトルネックになるため、WebP/AVIFの採用、width最適化、srcset/sizes設計をセットで。
  • 可読性とコントラスト:暗幕(オーバーレイ)でテキストのコントラストを担保し、prefers-reduced-motion配慮で動きを弱める分岐を用意すると丁寧。
  • フォーカス可視性:停止・再生ボタンはキーボード操作に対応し、focus-visibleでリングを明示。
  • 自動スクロールの可否:ニュースや商品群のように常に動くUIは、ユーザーが自発的に止められる手段(ボタン、ホバー停止)を用意するのが望ましい。
  • コンテンツ優先:ヒーローの重要コピーは背景化しない。読み上げや翻訳の対象になる本文テキストと、見た目だけの装飾テキストを分ける。

(元記事の主張である「CSSのみは軽く、挙動の理屈を理解しやすい」点を土台に、実務上の配慮を付け加えています) 。


9. 運用指針:デザインシステムへの落とし込み

  • スライダー方針
    • ただ見せる「ループ演出」→ CSSのみ(停止・再生だけJS)
    • ユーザー操作で進む「カルーセル」→ JSライブラリ(スクリーンリーダー対応、ページング、スワイプ感など)
  • パラメータ表
    • duration(ループ時間)/columns(縦横の列数)/overlay(暗幕の有無と濃度)/textPolicy(テキスト配置)/clipShape(角丸やクリッピング)
  • 検証端末
    • iOS Safari/Android Chrome/主要PCブラウザに加え、低リフレッシュ端末での滑らかさ確認をルーチン化。
  • 失敗パターン管理
    • 画像位置ズレ、角丸崩れ、コントラスト不足、object-fit対応漏れ、停止手段なし、画像重すぎ。

10. コピペで使えるテンプレート集

10-1. フェード+ズーム(3枚/ヒーロー)

  • 本文2章のコードをベースに、–duration: 24sのCSS変数化で案件ごとに調整しやすく。
:root { --duration: 24s; }
.img-01 { animation: slide-01 var(--duration) infinite; }
.img-02 { animation: slide-02 var(--duration) infinite; }
.img-03 { animation: slide-03 var(--duration) infinite; }



10-2. 横流しロゴスライダー(軽量・無限)

.logo-rail {
  display:flex; overflow:hidden; gap:24px;
  mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.logo-track {
  display:flex; gap:24px; animation: marquee 20s linear infinite;
}
.logo-track img { height:48px; width:auto; object-fit:contain; }
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

logo-trackを同じ内容で2本並べ、幅の半分だけ移動させると継ぎ目なしで無限に流れます(元記事の「3×3で循環させて3枚だけがループしているように見せる」発想を横方向へ) 。

10-3. ホバー停止と最小ボタン

  • 本文5章と6章の組み合わせ。PCはホバーで、SPはボタンで。

11. まとめ:CSSファーストで軽く、美しく、壊れにくく

  • CSSだけで作るスライドショーは、ヒーロー演出やロゴ流しなど「勝手に動いて見せたい」シーンでとても強力。停止・再生だけ最小限のJSを足せば、操作性と配慮も両立できます。
  • 背景画像を使う構造は、暗幕・テキスト合成・角丸やクリップまで含めてデザインの自由度が高い(元記事の設計思想) 。
  • iOSとAndroidでの背景位置のズレやborder-radiusの差異など、実機検証ポイントを押さえつつ、パフォーマンス/アクセシビリティの要件をシステム化しましょう(元記事の注意点も参照)
(Visited 1 times, 1 visits today)