波形セパレーター
速度の異なる波SVGを重ねて横スクロールさせ、セクションの境界を動的に区切ります。LPのヒーロー下端に好適。
ライブデモ
使用例(お題: カフェ MOON BREW)
この技法を「カフェ MOON BREW」というテーマのダミーサイトで実際に使った例です。
HTML
<!-- MOON BREW:ヒーローとメニューを波形セパレーターで区切る -->
<div class="mb-page">
<!-- 上:ヒーロー -->
<section class="mb-top">
<span class="mb-top__tag">TODAY'S BREW</span>
<h2 class="mb-top__title">琥珀色の、ひとやすみ。</h2>
<p class="mb-top__sub">深煎りのコクと余韻をどうぞ。</p>
<!-- 主役:速度違いの波を重ねて境界を動かす -->
<div class="mb-waves" aria-hidden="true">
<svg class="mb-wave mb-w1" viewBox="0 0 1440 120" preserveAspectRatio="none">
<path d="M0,60 C240,110 480,10 720,60 C960,110 1200,10 1440,60 L1440,120 L0,120 Z" />
</svg>
<svg class="mb-wave mb-w2" viewBox="0 0 1440 120" preserveAspectRatio="none">
<path d="M0,70 C240,20 480,120 720,70 C960,20 1200,120 1440,70 L1440,120 L0,120 Z" />
</svg>
<svg class="mb-wave mb-w3" viewBox="0 0 1440 120" preserveAspectRatio="none">
<path d="M0,80 C240,120 480,40 720,80 C960,120 1200,40 1440,80 L1440,120 L0,120 Z" />
</svg>
</div>
</section>
<!-- 下:メニュー -->
<section class="mb-menu">
<article class="mb-item">
<span class="mb-item__name">本日のドリップ</span>
<span class="mb-item__price">¥520</span>
</article>
<article class="mb-item">
<span class="mb-item__name">カフェラテ</span>
<span class="mb-item__price">¥580</span>
</article>
<article class="mb-item">
<span class="mb-item__name">焦がしキャラメルモカ</span>
<span class="mb-item__price">¥650</span>
</article>
</section>
</div>
CSS
/* MOON BREW:波形セパレーターでヒーローとメニューを区切る */
:root {
--cream: #f5ede1;
--brown: #2b1d12;
--amber: #c98a3b;
}
* { box-sizing: border-box; }
body {
margin: 0;
height: 400px;
font-family: "Hiragino Kaku Gothic ProN", "Yu Gothic", system-ui, sans-serif;
background: var(--cream);
overflow: hidden;
}
.mb-page { height: 400px; display: grid; grid-template-rows: 1fr auto; }
/* 上:コーヒー写真ヒーロー */
.mb-top {
position: relative;
display: grid;
align-content: center;
justify-items: center;
text-align: center;
color: #fff;
padding: 18px 22px 0;
background:
linear-gradient(180deg, rgba(43,29,18,0.45), rgba(43,29,18,0.7)),
url("https://picsum.photos/800/400?random=44") center/cover no-repeat;
}
.mb-top__tag {
font-size: 10px;
letter-spacing: 0.3em;
font-weight: 700;
color: #ffe7c4;
}
.mb-top__title {
margin: 10px 0 6px;
font-size: 26px;
font-weight: 800;
font-family: "Hiragino Mincho ProN", "Yu Mincho", serif;
}
.mb-top__sub { margin: 0; font-size: 12.5px; color: rgba(255,255,255,0.9); }
/* 主役:波の層。下端に固定し横スクロールで揺らす */
.mb-waves {
position: absolute;
left: 0;
right: 0;
bottom: -1px;
height: 70px;
}
.mb-wave {
position: absolute;
left: 0;
bottom: 0;
width: 200%;
height: 100%;
}
.mb-wave path { fill: var(--cream); }
.mb-w1 path { fill: rgba(245, 237, 225, 0.45); }
.mb-w2 path { fill: rgba(245, 237, 225, 0.75); }
.mb-w3 path { fill: var(--cream); }
.mb-w1 { animation: mbWave 9s linear infinite; }
.mb-w2 { animation: mbWave 6s linear infinite; }
.mb-w3 { animation: mbWave 4s linear infinite; }
@keyframes mbWave {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
/* 下:メニュー */
.mb-menu { display: grid; gap: 2px; padding: 14px 26px 22px; background: var(--cream); }
.mb-item {
display: flex;
align-items: baseline;
justify-content: space-between;
padding: 9px 0;
border-bottom: 1px dashed rgba(43, 29, 18, 0.14);
color: var(--brown);
}
.mb-item:last-child { border-bottom: none; }
.mb-item__name { font-size: 14px; font-weight: 600; }
.mb-item__price { font-size: 14px; font-weight: 800; color: var(--amber); }
@media (prefers-reduced-motion: reduce) {
.mb-wave { animation: none; }
}
JavaScript
// 波アニメは純CSS。タブ非表示時はアニメを止めて無駄な描画を省く
const waves = document.querySelectorAll(".mb-wave");
if (waves.length) {
const setState = () => {
// 非表示なら一時停止、復帰で再開
const state = document.hidden ? "paused" : "running";
waves.forEach((w) => { w.style.animationPlayState = state; });
};
document.addEventListener("visibilitychange", setState);
setState(); // 初期反映
}
コード
HTML
<!-- 波形セパレーター: 重なる波SVGを横スクロールさせてセクション境界を演出 -->
<section class="top">
<h2 class="head">Wave Separator</h2>
<p class="sub">セクションを区切る動く波</p>
<!-- 波の層(複数のpathを速度・色違いで重ねる) -->
<div class="waves" aria-hidden="true">
<svg class="wave w1" viewBox="0 0 1440 120" preserveAspectRatio="none">
<path d="M0,60 C240,110 480,10 720,60 C960,110 1200,10 1440,60 L1440,120 L0,120 Z" />
</svg>
<svg class="wave w2" viewBox="0 0 1440 120" preserveAspectRatio="none">
<path d="M0,70 C240,20 480,120 720,70 C960,20 1200,120 1440,70 L1440,120 L0,120 Z" />
</svg>
<svg class="wave w3" viewBox="0 0 1440 120" preserveAspectRatio="none">
<path d="M0,80 C240,120 480,40 720,80 C960,120 1200,40 1440,80 L1440,120 L0,120 Z" />
</svg>
</div>
</section>
<section class="bottom">
<p>↓ 下のセクション</p>
</section>
CSS
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
font-family: "Segoe UI", system-ui, sans-serif;
display: flex;
flex-direction: column;
}
/* 上セクション: グラデ背景 */
.top {
position: relative;
flex: 1 1 auto;
min-height: 230px;
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%);
color: #fff;
display: grid;
align-content: center;
justify-items: center;
gap: 6px;
padding: 30px 20px 0;
overflow: hidden;
}
.head {
margin: 0;
font-size: clamp(20px, 5vw, 30px);
letter-spacing: .02em;
text-shadow: 0 4px 20px rgba(0, 0, 0, .25);
}
.sub {
margin: 0;
font-size: 13px;
opacity: .9;
letter-spacing: .08em;
}
/* 波の重なり。下端にぴったり配置 */
.waves {
position: absolute;
left: 0; right: 0; bottom: -1px;
height: 110px;
line-height: 0;
}
.wave {
position: absolute;
left: 0; bottom: 0;
width: 200%; /* 2枚分の幅で途切れず流す */
height: 100%;
}
/* 各層の色・速度・透明度を変えて立体感 */
.w1 path { fill: rgba(248, 250, 252, .35); }
.w2 path { fill: rgba(248, 250, 252, .55); }
.w3 path { fill: #f8fafc; }
.w1 { animation: drift 9s linear infinite; }
.w2 { animation: drift 6s linear infinite reverse; }
.w3 { animation: drift 4.5s linear infinite; }
@keyframes drift {
from { transform: translateX(0); }
to { transform: translateX(-50%); } /* 半分動かすとシームレス */
}
/* 下セクション */
.bottom {
flex: 0 0 auto;
background: #f8fafc;
color: #475569;
display: grid;
place-items: center;
padding: 18px;
font-size: 13px;
letter-spacing: .06em;
}
@media (prefers-reduced-motion: reduce) {
.wave { animation: none !important; width: 100%; }
}
JavaScript
// 波形セパレーターはCSSアニメーションだけで動作するためJSは不要です。
🤖 AIエージェント用プロンプト
このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「波形セパレーター」の効果を追加してください。
# 追加してほしい効果
波形セパレーター(SVG エフェクト)
速度の異なる波SVGを重ねて横スクロールさせ、セクションの境界を動的に区切ります。LPのヒーロー下端に好適。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- 波形セパレーター: 重なる波SVGを横スクロールさせてセクション境界を演出 -->
<section class="top">
<h2 class="head">Wave Separator</h2>
<p class="sub">セクションを区切る動く波</p>
<!-- 波の層(複数のpathを速度・色違いで重ねる) -->
<div class="waves" aria-hidden="true">
<svg class="wave w1" viewBox="0 0 1440 120" preserveAspectRatio="none">
<path d="M0,60 C240,110 480,10 720,60 C960,110 1200,10 1440,60 L1440,120 L0,120 Z" />
</svg>
<svg class="wave w2" viewBox="0 0 1440 120" preserveAspectRatio="none">
<path d="M0,70 C240,20 480,120 720,70 C960,20 1200,120 1440,70 L1440,120 L0,120 Z" />
</svg>
<svg class="wave w3" viewBox="0 0 1440 120" preserveAspectRatio="none">
<path d="M0,80 C240,120 480,40 720,80 C960,120 1200,40 1440,80 L1440,120 L0,120 Z" />
</svg>
</div>
</section>
<section class="bottom">
<p>↓ 下のセクション</p>
</section>
【CSS】
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
font-family: "Segoe UI", system-ui, sans-serif;
display: flex;
flex-direction: column;
}
/* 上セクション: グラデ背景 */
.top {
position: relative;
flex: 1 1 auto;
min-height: 230px;
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%);
color: #fff;
display: grid;
align-content: center;
justify-items: center;
gap: 6px;
padding: 30px 20px 0;
overflow: hidden;
}
.head {
margin: 0;
font-size: clamp(20px, 5vw, 30px);
letter-spacing: .02em;
text-shadow: 0 4px 20px rgba(0, 0, 0, .25);
}
.sub {
margin: 0;
font-size: 13px;
opacity: .9;
letter-spacing: .08em;
}
/* 波の重なり。下端にぴったり配置 */
.waves {
position: absolute;
left: 0; right: 0; bottom: -1px;
height: 110px;
line-height: 0;
}
.wave {
position: absolute;
left: 0; bottom: 0;
width: 200%; /* 2枚分の幅で途切れず流す */
height: 100%;
}
/* 各層の色・速度・透明度を変えて立体感 */
.w1 path { fill: rgba(248, 250, 252, .35); }
.w2 path { fill: rgba(248, 250, 252, .55); }
.w3 path { fill: #f8fafc; }
.w1 { animation: drift 9s linear infinite; }
.w2 { animation: drift 6s linear infinite reverse; }
.w3 { animation: drift 4.5s linear infinite; }
@keyframes drift {
from { transform: translateX(0); }
to { transform: translateX(-50%); } /* 半分動かすとシームレス */
}
/* 下セクション */
.bottom {
flex: 0 0 auto;
background: #f8fafc;
color: #475569;
display: grid;
place-items: center;
padding: 18px;
font-size: 13px;
letter-spacing: .06em;
}
@media (prefers-reduced-motion: reduce) {
.wave { animation: none !important; width: 100%; }
}
【JavaScript】
// 波形セパレーターはCSSアニメーションだけで動作するためJSは不要です。
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。