Ken Burns スライドショー
静止画をゆっくりズーム&パンしながらクロスフェードさせる映画的スライドショー。ヒーローバナーや背景演出に最適です。
ライブデモ
使用例(お題: アイドルグループ Sakura)
この技法を「アイドルグループ Sakura」というテーマのダミーサイトで実際に使った例です。
HTML
<!-- Sakura:ライブツアー告知ヒーロー(Ken Burns スライドショー) -->
<section class="sk-kb">
<!-- 各スチルがズーム&パンしながらクロスフェード -->
<div class="sk-kb__slide is-active" style="--img:url('https://picsum.photos/1000/700?random=41')"></div>
<div class="sk-kb__slide" style="--img:url('https://picsum.photos/1000/700?random=42')"></div>
<div class="sk-kb__slide" style="--img:url('https://picsum.photos/1000/700?random=43')"></div>
<!-- 桜の花びら -->
<span class="sk-kb__petal sk-kb__petal--1">❀</span>
<span class="sk-kb__petal sk-kb__petal--2">❀</span>
<!-- ヒーローコピー -->
<div class="sk-kb__overlay">
<p class="sk-kb__kicker">SAKURA SPRING TOUR 2026</p>
<h1 class="sk-kb__title">満開、君に届け。</h1>
<p class="sk-kb__lead">全国5都市をめぐる春のホールツアー、開幕。</p>
<a class="sk-kb__btn" href="#">ツアー日程を見る</a>
</div>
<div class="sk-kb__dots" role="tablist" aria-label="スライド"></div>
</section>
CSS
/* Sakura:ライブツアー告知ヒーロー(Ken Burns) */
:root {
--pink: #ffd1e0;
--deep: #5a2e44;
}
* { box-sizing: border-box; }
body {
margin: 0;
height: 400px;
font-family: "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
overflow: hidden;
}
.sk-kb {
position: relative;
width: 100%;
height: 400px;
overflow: hidden;
background: var(--deep);
}
/* スライド:背景画像をズーム&パン */
.sk-kb__slide {
position: absolute;
inset: 0;
background: var(--img) center/cover no-repeat;
opacity: 0;
transform: scale(1.05);
}
.sk-kb__slide.is-active {
opacity: 1;
animation: skKenBurns 6s ease-out forwards;
}
@keyframes skKenBurns {
0% { opacity: 0; transform: scale(1.18) translate(2%, -1%); }
12% { opacity: 1; }
100% { opacity: 1; transform: scale(1.02) translate(-2%, 1%); }
}
/* 桜ピンクのフィルター+暗幕 */
.sk-kb::before {
content: "";
position: absolute;
inset: 0;
z-index: 1;
background:
linear-gradient(180deg, rgba(90,46,68,0.15) 0%, rgba(90,46,68,0.7) 100%),
radial-gradient(120% 90% at 20% 100%, rgba(255,150,185,0.45), transparent 60%);
pointer-events: none;
}
/* 花びら */
.sk-kb__petal {
position: absolute;
z-index: 2;
color: rgba(255,209,224,0.85);
text-shadow: 0 2px 6px rgba(0,0,0,0.3);
pointer-events: none;
animation: skFall 7s linear infinite;
}
.sk-kb__petal--1 { top: -20px; left: 18%; font-size: 22px; }
.sk-kb__petal--2 { top: -20px; left: 72%; font-size: 16px; animation-duration: 9s; animation-delay: -3s; }
@keyframes skFall {
0% { transform: translateY(-20px) rotate(0); opacity: 0; }
15% { opacity: 1; }
100% { transform: translateY(420px) rotate(360deg); opacity: 0; }
}
/* ヒーローコピー */
.sk-kb__overlay {
position: absolute;
left: 36px;
bottom: 40px;
z-index: 3;
color: #fff;
max-width: 360px;
}
.sk-kb__kicker {
margin: 0 0 8px;
font-size: 10px;
letter-spacing: 0.25em;
color: var(--pink);
}
.sk-kb__title {
margin: 0 0 8px;
font-size: 34px;
font-weight: 800;
line-height: 1.3;
font-family: "Hiragino Mincho ProN", "Yu Mincho", serif;
text-shadow: 0 3px 12px rgba(0,0,0,0.4);
}
.sk-kb__lead { margin: 0 0 16px; font-size: 13px; line-height: 1.8; color: rgba(255,255,255,0.92); }
.sk-kb__btn {
display: inline-block;
padding: 11px 24px;
border-radius: 999px;
background: var(--pink);
color: var(--deep);
font-size: 13px;
font-weight: 700;
text-decoration: none;
box-shadow: 0 8px 20px rgba(255,150,185,0.5);
transition: transform 0.2s ease;
}
.sk-kb__btn:hover { transform: translateY(-2px); }
/* インジケーター */
.sk-kb__dots {
position: absolute;
right: 24px;
bottom: 24px;
z-index: 3;
display: flex;
gap: 8px;
}
.sk-kb__dot {
width: 9px;
height: 9px;
padding: 0;
border: none;
border-radius: 50%;
background: rgba(255,255,255,0.4);
cursor: pointer;
transition: background 0.2s ease, transform 0.2s ease;
}
.sk-kb__dot[aria-selected="true"] { background: var(--pink); transform: scale(1.3); }
@media (prefers-reduced-motion: reduce) {
.sk-kb__slide.is-active { animation: none; }
.sk-kb__petal { animation: none; opacity: 0; }
.sk-kb__btn, .sk-kb__dot { transition: none; }
}
JavaScript
// スライドを一定間隔で切り替え、Ken Burns アニメを再トリガーする
const slides = Array.from(document.querySelectorAll(".sk-kb__slide"));
const dotsWrap = document.querySelector(".sk-kb__dots");
let index = 0;
let timer = null;
if (slides.length && dotsWrap) {
// ドット生成
const dots = slides.map((_, i) => {
const b = document.createElement("button");
b.className = "sk-kb__dot";
b.setAttribute("role", "tab");
b.setAttribute("aria-label", `スライド ${i + 1}`);
b.addEventListener("click", () => go(i));
dotsWrap.appendChild(b);
return b;
});
// 指定スライドを表示
const go = (next) => {
slides[index].classList.remove("is-active");
index = (next + slides.length) % slides.length;
const el = slides[index];
el.classList.remove("is-active");
void el.offsetWidth; // reflow でアニメ再生を保証
el.classList.add("is-active");
dots.forEach((d, i) => d.setAttribute("aria-selected", String(i === index)));
restart();
};
// 自動送り
const restart = () => {
if (timer) clearInterval(timer);
timer = setInterval(() => go(index + 1), 5000);
};
dots[0].setAttribute("aria-selected", "true");
restart();
}
コード
HTML
<!-- Ken Burns: ゆっくりズーム&パンするスライドショー -->
<div class="kb">
<!-- 各スライドが順番にズームしながらクロスフェード -->
<div class="kb__slide is-active" style="--img:url('https://picsum.photos/id/1018/1000/700')"></div>
<div class="kb__slide" style="--img:url('https://picsum.photos/id/1039/1000/700')"></div>
<div class="kb__slide" style="--img:url('https://picsum.photos/id/1043/1000/700')"></div>
<div class="kb__overlay">
<p class="kb__kicker">CINEMATIC</p>
<h2 class="kb__title">Ken Burns Effect</h2>
</div>
<!-- インジケーター -->
<div class="kb__dots" role="tablist" aria-label="スライド"></div>
</div>
CSS
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
background: #000;
font-family: "Segoe UI", system-ui, sans-serif;
}
/* ビューポート枠 */
.kb {
position: relative;
width: 100%;
height: 360px;
overflow: hidden;
background: #111;
}
/* スライド: 背景画像を拡大表示し、active のときだけ動かす */
.kb__slide {
position: absolute;
inset: 0;
background-image: var(--img);
background-size: cover;
background-position: center;
opacity: 0;
transform: scale(1.05);
transition: opacity 1.4s ease;
}
.kb__slide.is-active {
opacity: 1;
/* ゆっくりズーム&パン */
animation: kenburns 8s ease-in-out forwards;
}
@keyframes kenburns {
0% { transform: scale(1.05) translate(0, 0); }
100% { transform: scale(1.28) translate(-3%, -2%); }
}
/* 暗いビネット + テキスト */
.kb::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(to top, rgba(0, 0, 0, .7), transparent 55%);
pointer-events: none;
}
.kb__overlay {
position: absolute;
left: 32px;
bottom: 28px;
z-index: 2;
color: #fff;
text-shadow: 0 2px 12px rgba(0, 0, 0, .6);
}
.kb__kicker {
margin: 0 0 4px;
font-size: 12px;
letter-spacing: .4em;
color: #ffd479;
font-weight: 700;
}
.kb__title {
margin: 0;
font-size: clamp(24px, 5vw, 40px);
font-weight: 800;
letter-spacing: .02em;
}
/* ドット */
.kb__dots {
position: absolute;
right: 22px;
bottom: 22px;
z-index: 3;
display: flex;
gap: 8px;
}
.kb__dot {
width: 9px;
height: 9px;
border-radius: 50%;
border: none;
background: rgba(255, 255, 255, .4);
cursor: pointer;
padding: 0;
transition: background .3s ease, transform .3s ease;
}
.kb__dot[aria-selected="true"] { background: #fff; transform: scale(1.3); }
@media (prefers-reduced-motion: reduce) {
.kb__slide.is-active { animation: none; transform: scale(1.1); }
.kb__slide { transition: opacity .4s ease; }
}
JavaScript
// スライドを一定間隔で切り替え、Ken Burns アニメを再トリガーする
const slides = Array.from(document.querySelectorAll(".kb__slide"));
const dotsWrap = document.querySelector(".kb__dots");
let index = 0;
let timer = null;
if (slides.length && dotsWrap) {
// ドットを生成
const dots = slides.map((_, i) => {
const b = document.createElement("button");
b.className = "kb__dot";
b.setAttribute("role", "tab");
b.setAttribute("aria-label", `スライド ${i + 1}`);
b.addEventListener("click", () => go(i));
dotsWrap.appendChild(b);
return b;
});
// 指定スライドを表示
const go = (next) => {
slides[index].classList.remove("is-active");
index = (next + slides.length) % slides.length;
// animation を確実に再生させるため reflow を挟む
const el = slides[index];
el.classList.remove("is-active");
void el.offsetWidth;
el.classList.add("is-active");
dots.forEach((d, i) => d.setAttribute("aria-selected", String(i === index)));
restart();
};
// 自動送りタイマー
const restart = () => {
if (timer) clearInterval(timer);
timer = setInterval(() => go(index + 1), 5000);
};
// 初期表示
dots[0].setAttribute("aria-selected", "true");
restart();
}
🤖 AIエージェント用プロンプト
このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「Ken Burns スライドショー」の効果を追加してください。
# 追加してほしい効果
Ken Burns スライドショー(画像エフェクト)
静止画をゆっくりズーム&パンしながらクロスフェードさせる映画的スライドショー。ヒーローバナーや背景演出に最適です。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- Ken Burns: ゆっくりズーム&パンするスライドショー -->
<div class="kb">
<!-- 各スライドが順番にズームしながらクロスフェード -->
<div class="kb__slide is-active" style="--img:url('https://picsum.photos/id/1018/1000/700')"></div>
<div class="kb__slide" style="--img:url('https://picsum.photos/id/1039/1000/700')"></div>
<div class="kb__slide" style="--img:url('https://picsum.photos/id/1043/1000/700')"></div>
<div class="kb__overlay">
<p class="kb__kicker">CINEMATIC</p>
<h2 class="kb__title">Ken Burns Effect</h2>
</div>
<!-- インジケーター -->
<div class="kb__dots" role="tablist" aria-label="スライド"></div>
</div>
【CSS】
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
background: #000;
font-family: "Segoe UI", system-ui, sans-serif;
}
/* ビューポート枠 */
.kb {
position: relative;
width: 100%;
height: 360px;
overflow: hidden;
background: #111;
}
/* スライド: 背景画像を拡大表示し、active のときだけ動かす */
.kb__slide {
position: absolute;
inset: 0;
background-image: var(--img);
background-size: cover;
background-position: center;
opacity: 0;
transform: scale(1.05);
transition: opacity 1.4s ease;
}
.kb__slide.is-active {
opacity: 1;
/* ゆっくりズーム&パン */
animation: kenburns 8s ease-in-out forwards;
}
@keyframes kenburns {
0% { transform: scale(1.05) translate(0, 0); }
100% { transform: scale(1.28) translate(-3%, -2%); }
}
/* 暗いビネット + テキスト */
.kb::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(to top, rgba(0, 0, 0, .7), transparent 55%);
pointer-events: none;
}
.kb__overlay {
position: absolute;
left: 32px;
bottom: 28px;
z-index: 2;
color: #fff;
text-shadow: 0 2px 12px rgba(0, 0, 0, .6);
}
.kb__kicker {
margin: 0 0 4px;
font-size: 12px;
letter-spacing: .4em;
color: #ffd479;
font-weight: 700;
}
.kb__title {
margin: 0;
font-size: clamp(24px, 5vw, 40px);
font-weight: 800;
letter-spacing: .02em;
}
/* ドット */
.kb__dots {
position: absolute;
right: 22px;
bottom: 22px;
z-index: 3;
display: flex;
gap: 8px;
}
.kb__dot {
width: 9px;
height: 9px;
border-radius: 50%;
border: none;
background: rgba(255, 255, 255, .4);
cursor: pointer;
padding: 0;
transition: background .3s ease, transform .3s ease;
}
.kb__dot[aria-selected="true"] { background: #fff; transform: scale(1.3); }
@media (prefers-reduced-motion: reduce) {
.kb__slide.is-active { animation: none; transform: scale(1.1); }
.kb__slide { transition: opacity .4s ease; }
}
【JavaScript】
// スライドを一定間隔で切り替え、Ken Burns アニメを再トリガーする
const slides = Array.from(document.querySelectorAll(".kb__slide"));
const dotsWrap = document.querySelector(".kb__dots");
let index = 0;
let timer = null;
if (slides.length && dotsWrap) {
// ドットを生成
const dots = slides.map((_, i) => {
const b = document.createElement("button");
b.className = "kb__dot";
b.setAttribute("role", "tab");
b.setAttribute("aria-label", `スライド ${i + 1}`);
b.addEventListener("click", () => go(i));
dotsWrap.appendChild(b);
return b;
});
// 指定スライドを表示
const go = (next) => {
slides[index].classList.remove("is-active");
index = (next + slides.length) % slides.length;
// animation を確実に再生させるため reflow を挟む
const el = slides[index];
el.classList.remove("is-active");
void el.offsetWidth;
el.classList.add("is-active");
dots.forEach((d, i) => d.setAttribute("aria-selected", String(i === index)));
restart();
};
// 自動送りタイマー
const restart = () => {
if (timer) clearInterval(timer);
timer = setInterval(() => go(index + 1), 5000);
};
// 初期表示
dots[0].setAttribute("aria-selected", "true");
restart();
}
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。