スマホ主流のいま、トップのヒーローエリアやロゴスライダーはサイトの第一印象を決める重要パーツです。ところが、ライブラリに頼りすぎると読み込みサイズの増加、バージョン差異による不具合、カスタマイズの難しさに悩みがち。そこで本稿では、「HTMLとCSSのみでWebサイト用のスライドショーを作る(ボタン付きの解説あり)」という良質な解説を出発点に、実務で使える設計・コード・落とし穴回避・アクセシビリティ配慮までを体系化しました。基礎はCSSだけで、必要最小限のJavaScriptで停止・再生ボタンを追加する方針です(元記事の構成と趣旨) 。
目次
- なぜCSSだけで作るのか:実務メリット
- 「フェード+ズーム」3枚スライドの基本構成
- 意匠の拡張:半透明オーバーレイ、テキストの合成、角丸やクリッピング
- 「流れる」スライドの実装:縦スクロール型と横スクロール型
- ホバーで一時停止、タップ環境への配慮
- 停止・再生ボタンの追加(最小JS)
- 実務の落とし穴:iOSとAndroidの表示差/背景位置とオブジェクトフィット
- パフォーマンスとアクセシビリティ設計
- 運用指針:デザインシステムへの落とし込み
- コピペで使えるテンプレート集
- まとめ:CSSファーストで軽く、美しく、壊れにくく
- さらに深く学ぶための参考
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-fitとbackground-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の差異など、実機検証ポイントを押さえつつ、パフォーマンス/アクセシビリティの要件をシステム化しましょう(元記事の注意点も参照)

