「海」を表現する

波・光・泡・きらめき。海の空気感を写真素材に頼らず、CSS/SVGの軽量な表現で再現するテクニック。

このページについて

  • 「海の表現」とは:波の動き・水中の光・泡など、海を連想させる視覚要素。実写を使わずに抽象表現で「海らしさ」を伝えると、軽量で世界観の統一もしやすい。
  • こんな時に使う:マリンスポーツ・リゾート・水族館・夏キャンペーン・ダイビングショップ・湘南エリアの店舗サイトなど。
  • 関連タグ🌿 癒し(準備中)❄️ 清涼感(準備中)☁️ 空(準備中)
  • AIへの伝え方のコツ:「海っぽく」では曖昧。「多層の波」「上から差す光芒」「泡の上昇」など、このページの具体的な表現名で指示する。

表現の引き出し

🎨 重なる波

📝 表現の語彙

日本語: 重なる波、多層の波、うねり、波打つ
英語: layered waves, overlapping waves, undulating surface
抽象キーワード: rhythm, depth, fluidity

💬 AIへの指示テンプレ

「ヒーローセクションの下部に、4層の重なる波のアニメーションを追加してください。波形は波長・振幅を不規則にしたQカーブの連続で作り(規則的なサインカーブにしない)、奥の層ほどなだらかで遅く、手前の層ほど波長が細かく速く流れるようにしてください。各層は同一形状2枚連結のtranslateXループ+周期の異なる上下うねりを重ね、最前面の波にはfeTurbulence + feDisplacementMapフィルターで水面の揺らぎを加えてください。」

🎯 似合うシーン

リゾート・マリンスポーツ・水族館・夏のキャンペーンLP・ビーチ系飲食店

🔧 実装手法

不規則な波長・振幅のSVG path × 4層の横ループ + 層ごとに振幅・周期を変えた上下うねり + feTurbulence/feDisplacementMapによる揺らぎ(最前面のみ)

📄 コード例を見る
html
<div class="wave-stage">
  <!-- 揺らぎフィルター(負荷が高いため最前面の波にのみ適用) -->
  <svg width="0" height="0" aria-hidden="true">
    <filter id="waveTurbulence">
      <!-- numOctaves=1 + 低い baseFrequency で、ギザつかない大きくなだらかな揺らぎにする -->
      <feTurbulence type="fractalNoise" baseFrequency="0.005 0.012"
        numOctaves="1" seed="3" result="noise">
        <animate attributeName="baseFrequency" dur="17s"
          values="0.005 0.012; 0.006 0.016; 0.005 0.012" repeatCount="indefinite" />
      </feTurbulence>
      <feDisplacementMap in="SourceGraphic" in2="noise" scale="5" />
    </filter>
  </svg>
  <!-- 4層構成。波形は波長・振幅を不規則にした Q カーブの連続で作る -->
  <!-- 各層は「上下うねり」ラッパー ×「同一path×2連結の横ループ」 -->
  <div class="wave-bob wave-bob-1">
    <div class="wave-layer wave-1">
      <svg viewBox="0 0 800 120" preserveAspectRatio="none">
        <path d="M0,58 Q55,48 110,56 Q150,62 210,52 Q270,42 330,54 Q380,64 440,54
                 Q500,42 560,56 Q610,66 670,56 Q730,46 800,58 L800,120 L0,120 Z"
          fill="#dbeafe" />
      </svg>
      <svg><!-- 同じpath --></svg>
    </div>
  </div>
  <div class="wave-bob wave-bob-2"><!-- 第2層 --></div>
  <div class="wave-bob wave-bob-3"><!-- 第3層(波長を細かく) --></div>
  <div class="wave-bob wave-bob-4"><!-- 最前面(さらに細かい波長、filter適用) --></div>
</div>
css
.wave-stage {
  position: relative;
  height: 180px;
  border-radius: 8px;
  overflow: hidden;
  background: linear-gradient(180deg, #7dd3fc 0%, #38bdf8 35%, #0284c7 70%, #075985 100%);
}
/* 上下のうねり。奥は小さくゆっくり、手前は大きく速く(素数的な周期差) */
.wave-bob { position: absolute; left: 0; width: 100%; }
/* うねりや揺らぎで下端が浮いて余白が出ないよう、揺れ幅ぶん下にはみ出させる */
.wave-bob-1 { height: 118px; bottom: -5px;  animation: waveBob1 13s ease-in-out infinite alternate; }
.wave-bob-2 { height: 100px; bottom: -6px;  animation: waveBob2 11s ease-in-out infinite alternate; animation-delay: -5s; }
.wave-bob-3 { height: 84px;  bottom: -7px;  animation: waveBob3 9s  ease-in-out infinite alternate; animation-delay: -2s; }
.wave-bob-4 { height: 66px;  bottom: -12px; animation: waveBob4 7s  ease-in-out infinite alternate; animation-delay: -3.5s; }
@keyframes waveBob1 { from { transform: translateY(0); } to { transform: translateY(-4px); } }
@keyframes waveBob2 { from { transform: translateY(0); } to { transform: translateY(-5px); } }
@keyframes waveBob3 { from { transform: translateY(0); } to { transform: translateY(-6px); } }
@keyframes waveBob4 { from { transform: translateY(0); } to { transform: translateY(-8px); } }
/* 横の流れ。-50% 移動で継ぎ目なくループ(水の流れは等速でよい) */
.wave-layer { display: flex; width: 200%; height: 100%; }
.wave-layer svg { width: 50%; height: 100%; flex-shrink: 0; }
.wave-1 { animation: waveDrift 34s linear infinite; opacity: .3; }
.wave-2 { animation: waveDrift 26s linear infinite; opacity: .45; }
.wave-3 { animation: waveDrift 19s linear infinite; opacity: .65; }
.wave-4 { animation: waveDrift 13s linear infinite; opacity: .9;
  filter: url(#waveTurbulence); } /* 揺らぎは最前面のみ */
@keyframes waveDrift {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
📖 関連: キーフレームアニメーション

🎨 海中の光芒

📝 表現の語彙

日本語: 光芒、水中に差す光、光のカーテン、木漏れ日(水中版)
英語: underwater light rays, god rays, light shafts, crepuscular rays
抽象キーワード: luminosity, serenity, depth

💬 AIへの指示テンプレ

「セクション背景を深い青の海中にして、上から光の筋(光芒)が差し込む演出を追加してください。光芒は明るいコアの光と幅広で淡いグロー光を混ぜて重ね、mix-blend-mode: screen で重なりが光るようにしてください。左右に岸壁のシルエットを置き(奥はblurで霞ませ、手前はシャープに)、下に行くほど暗くなる深度の霧グラデーションで奥行きを出してください。各光芒は上端を支点にゆっくり左右に揺れ、小さな微粒子がゆっくり漂い上がるアクセントも加えてください。」

🎯 似合うシーン

ダイビング・水族館・スパ・瞑想/リラクゼーション・深海テーマのクリエイティブサイト

🔧 実装手法

コア+グローの2種の光芒(screen合成・支点回転)+ 奥行き2段の岸壁シルエット + 深度の霧グラデーション + 微粒子の多重周期浮遊

📄 コード例を見る
html
<div class="ray-stage">
  <div class="ray-surface"></div>
  <!-- 岸壁のシルエット。奥(blur+薄め)と手前(シャープ)の2段で奥行きを出す -->
  <svg class="ray-rocks" viewBox="0 0 400 180" preserveAspectRatio="none">
    <path class="rock-far" d="M0,180 L0,58 Q36,74 28,100 Q48,122 40,148 Q54,164 48,180 Z" fill="#0a2b42" />
    <path class="rock-far" d="M400,180 L400,46 Q364,62 372,90 Q352,114 362,140 Q346,160 352,180 Z" fill="#0a2b42" />
    <path d="M0,180 L0,98 Q26,110 18,132 Q38,148 30,166 Q42,174 38,180 Z" fill="#03141f" />
    <path d="M400,180 L400,90 Q376,102 384,124 Q366,140 374,158 Q360,170 364,180 Z" fill="#03141f" />
  </svg>
  <!-- 光芒。明るいコアの光と、幅広で淡いグロー光を混ぜる -->
  <div class="ray" style="left: 6%;  width: 44px;  opacity: .55; --tilt: -9deg; --dur: 11s; filter: blur(4px)"></div>
  <div class="ray" style="left: 22%; width: 90px;  opacity: .28; --tilt: -5deg; --dur: 23s; filter: blur(10px)"></div>
  <!-- ...コア5本+グロー2本の計7本... -->

  <!-- 深度の霧。下に行くほど光が届かない -->
  <div class="ray-depth"></div>

  <!-- 漂う微粒子。上昇と左右の揺れは別アニメで合成 -->
  <div class="mote" style="left: 20%; width: 2px; height: 2px; --dur: 23s; --sway: 3.7s; --mo: 0.4">
    <div class="mote-dot"></div>
  </div>
</div>
css
.ray-stage {
  position: relative;
  height: 180px;
  border-radius: 8px;
  overflow: hidden;
  background: linear-gradient(180deg, #0c4a6e 0%, #082f49 60%, #041e33 100%);
}
/* 水面の明るさの気配 */
.ray-surface {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 30px;
  background: linear-gradient(180deg, rgba(186,230,253,0.25), transparent);
}
.ray-rocks { position: absolute; inset: 0; width: 100%; height: 100%; }
.rock-far { filter: blur(2px); opacity: .8; } /* 奥の岩は霞ませる */
/* 上が狭く下に広がる光のカーテン。screen合成で岸壁にも光が当たる */
.ray {
  position: absolute;
  top: -12px;
  height: 200px;
  clip-path: polygon(38% 0, 62% 0, 100% 100%, 0 100%);
  background: linear-gradient(180deg,
    rgba(224,242,254,0.65) 0%, rgba(186,230,253,0.25) 45%, transparent 85%);
  mix-blend-mode: screen;
  transform-origin: top center;
  transform: rotate(var(--tilt));
  animation: raySway var(--dur) ease-in-out infinite alternate;
}
@keyframes raySway {
  from { transform: rotate(calc(var(--tilt) - 3deg)); }
  to   { transform: rotate(calc(var(--tilt) + 3deg)); }
}
/* 深度の霧:下に行くほど暗く、光芒が溶けて消える */
.ray-depth {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 35%, rgba(2,10,18,0.6) 100%);
}
/* 微粒子:ゆっくり上昇(19〜29s)×短周期の左右揺れ */
.mote {
  position: absolute;
  bottom: -10px;
  animation: moteRise var(--dur) ease-in-out infinite;
}
@keyframes moteRise {
  0%   { transform: translateY(0); opacity: 0; }
  12%  { opacity: var(--mo); }
  88%  { opacity: var(--mo); }
  100% { transform: translateY(-200px); opacity: 0; }
}
.mote-dot {
  width: 100%; height: 100%;
  border-radius: 9999px;
  background: #e0f2fe;
  animation: moteSway var(--sway) ease-in-out infinite alternate;
}
@keyframes moteSway {
  from { transform: translateX(-6px); }
  to   { transform: translateX(6px); }
}
📖 関連: フィルター

🎨 泡の上昇

📝 表現の語彙

日本語: 泡、気泡、泡の上昇、あぶく
英語: rising bubbles, air bubbles, effervescence
抽象キーワード: buoyancy, playfulness, freshness

💬 AIへの指示テンプレ

「水中背景に、大小の泡が揺れながら上昇するアニメーションを追加してください。遠近を意識して、手前の泡は大きく・速く・くっきり、奥の泡は小さく・遅く・薄くわずかにぼかしてください。泡は radial-gradient の左上ハイライトで球体感を出し、白・シアン寄り・青寄りなど色味と、scaleXのわずかなつぶれで1つずつ個性を出してください。上昇(ease-in)と横揺れ(内側要素の別アニメ)の2軸を合成し、上端で薄く拡大しながら消してください。」

🎯 似合うシーン

炭酸飲料・ビール・水族館・子供向けコンテンツ・洗剤/シャンプー系LP

🔧 実装手法

depth(遠近)を軸に速度・サイズ・濃さ・ボケを連動させた泡 + 色味3種とscaleXのつぶれで個性 + 上昇と横揺れの2軸合成

📄 コード例を見る
tsx
// 泡12個。depth(奥行き)を軸に速度・サイズ・濃さ・ボケを連動させる
const BUBBLE_TINTS = [
  // 白 / シアン寄り / 青寄り --- 泡ごとに色の個性を出す
  "radial-gradient(circle at 30% 30%, rgba(255,255,255,0.85), rgba(255,255,255,0.15) 45%, rgba(255,255,255,0.05) 70%)",
  "radial-gradient(circle at 32% 28%, rgba(236,254,255,0.9), rgba(165,243,252,0.18) 48%, rgba(165,243,252,0.05) 72%)",
  "radial-gradient(circle at 28% 32%, rgba(239,246,255,0.8), rgba(191,219,254,0.2) 42%, rgba(191,219,254,0.06) 68%)",
];
const bubbles = Array.from({ length: 12 }, (_, i) => {
  const j1 = ((i * 7919) % 100) / 100;       // depth: 0=奥, 1=手前
  const j2 = ((i * 104729) % 100) / 100;
  const j3 = ((i * 1299709) % 100) / 100;
  const depth = j1;
  return {
    left: 4 + ((i * 9973) % 90),             // %
    size: 5 + depth * 24,                    // 手前ほど大きい
    dur: 13 - depth * 8,                     // 手前は速く(5s)、奥は遅く(13s)
    delay: -(j2 * 13),
    sway: 2.3 + j2 * 1.4,
    amp: 2 + (1 - depth) * 7,                // 小さい泡ほど大きく揺れる
    opacity: 0.45 + depth * 0.55,            // 奥は薄い
    blur: (1 - depth) * 1.2,                 // 奥はわずかにボケる
    squish: 0.92 + j3 * 0.16,                // 真円でない微妙なつぶれ
    tint: i % 3,
  };
});

<div className="bubble-stage">
  {bubbles.map((b, i) => (
    <div key={i} className="bubble-rise"
      style={{
        left: `${b.left}%`, width: b.size, height: b.size,
        filter: `blur(${b.blur}px)`,
        "--dur": `${b.dur}s`, "--sway": `${b.sway}s`,
        "--amp": `${b.amp}px`, "--bo": b.opacity, "--squish": b.squish,
        animationDelay: `${b.delay}s`,
      }}>
      <div className="bubble" style={{ background: BUBBLE_TINTS[b.tint] }} />
    </div>
  ))}
</div>
css
.bubble-stage {
  position: relative;
  height: 180px;
  border-radius: 8px;
  overflow: hidden;
  background: linear-gradient(180deg, #38bdf8 0%, #0369a1 100%);
}
/* 上昇は ease-in(浮力で加速)。上端で薄く拡大して消える */
.bubble-rise {
  position: absolute;
  bottom: -32px;
  animation: bubbleRise var(--dur) ease-in infinite;
}
@keyframes bubbleRise {
  0%   { transform: translateY(0) scale(1); opacity: 0; }
  10%  { opacity: var(--bo); }
  88%  { opacity: var(--bo); transform: translateY(-196px) scale(1); }
  100% { transform: translateY(-214px) scale(1.3); opacity: 0; }
}
/* 左上ハイライトで球体感。横揺れ+微妙なつぶれは内側要素の別アニメ */
.bubble {
  width: 100%; height: 100%;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.35);
  animation: bubbleSway var(--sway) ease-in-out infinite alternate;
}
@keyframes bubbleSway {
  from { transform: translateX(calc(var(--amp) * -1)) scaleX(var(--squish)); }
  to   { transform: translateX(var(--amp)) scaleX(1); }
}
📖 関連: グラデーション

🎨 水面のきらめき

📝 表現の語彙

日本語: きらめき、水面の反射、波光、光の点滅
英語: sparkling water, sun glitter, shimmering surface
抽象キーワード: brilliance, transience, delight

💬 AIへの指示テンプレ

「夕方の海の水面が、きらきらと光る演出を作ってください。海は2色の青のランダムな太さの横ストライプで描き、ストライプの境界はぼかした上で波立つ曲線にし、各ラインをランダムな周期でゆっくり横に揺らしてください(奥に行くほど波は小さく、ストライプは細かく)。太陽の反射の帯を海面に縦に伸ばし(mix-blend-mode: overlay でゆっくり明滅)、きらめきは両端が緩やかに尖るレンズ形で水面全体に散らしつつ、太陽の下に最も多く配置してください。奥ほど細く短く・手前ほど長くし、明滅と波に乗る上下動を別アニメで重ねてください。」

🎯 似合うシーン

リゾートホテル・クルーズ・夕方の演出・サマーキャンペーン・ウェディング(海辺)

🔧 実装手法

境界を波立たせた2色の青ストライプ(blur+ゆっくり横揺れ、奥ほど波小さく)+ レンズ形きらめきを全面散布+太陽下に密度集中 + 明滅と波に乗る上下動の2アニメ合成

📄 コード例を見る
tsx
// ストライプの波立つ上端(サインカーブ的なQの連続。±20pxはみ出させて揺れの隙間を防ぐ)
function waveEdgePath(y, amp, wl, startUp) {
  let d = `M-20,${y}`;
  let up = startUp;
  for (let x = -20; x < 430; x += wl / 2) {
    d += ` Q${x + wl / 4},${y + (up ? -amp : amp)} ${x + wl / 2},${y}`;
    up = !up;
  }
  return `${d} L430,130 L-20,130 Z`;
}

// 海は2色の青のランダムな太さのストライプ。境界はぼかし、波立たせる
const seaStripes = (() => {
  const stripes = [];
  let y = 0;
  let i = 0;
  while (y < 122) {
    const j1 = ((i * 7919) % 100) / 100;
    const j2 = ((i * 104729) % 100) / 100;
    const j3 = ((i * 1299709) % 100) / 100;
    const depth = y / 120;                       // 0=水平線, 1=手前
    const t = (1.5 + depth * 12) * (0.6 + j1 * 0.8); // 奥は細く、手前は太く
    const amp = (0.3 + depth * 2.4) * (0.7 + j3 * 0.6); // 奥に行くほど波は小さく
    const wl = 46 + j2 * 50;                     // 波長もランダム
    stripes.push({
      d: waveEdgePath(y, amp, wl, i % 2 === 0),
      color: i % 2 ? "#0369a1" : "#0ea5e9",
      blur: 0.4 + (1 - depth) * 1.4,             // 全境界をぼかす(奥ほど強く)
      // 線ごとにゆっくり左右へ往復。向き(符号)・振幅・周期・位相をすべてバラす
      swayAmp: (i % 2 ? 1 : -1) * (5 + depth * 9) * (0.8 + j3 * 0.4),
      swayDur: 7 + j2 * 10,
      swayDelay: -(j1 * 12),
    });
    y += t;
    i++;
  }
  return stripes;
})();

// きらめき56個。水面全体に散らしつつ、太陽の下に密度を寄せる
const glints = Array.from({ length: 56 }, (_, i) => {
  const j1 = ((i * 7919) % 100) / 100;
  const j2 = ((i * 104729) % 100) / 100;
  const j3 = ((i * 1299709) % 100) / 100;
  const depth = j1;                          // 0=水平線際, 1=手前
  // 1/3は水面全体に散らし、残りは太陽の反射帯の近くに集める
  const x =
    i % 3 === 0 ? 8 + j2 * 384 : 200 + (j2 - 0.5) * 2 * (25 + j3 * j3 * 140);
  const y = 5 + depth * 108;
  const len = 2 + depth * 22;                // 奥は短く、手前は長く
  const h = 0.5 + depth * 1.4;               // 中央の太さ(奥は細い)
  const sag = (j3 - 0.5) * depth * 2;        // わずかな湾曲
  return {
    // 両端が緩やかに尖るレンズ形。中央が最も太く、端に行くほど細い
    d: `M${x - len / 2},${y} Q${x},${y + sag - h} ${x + len / 2},${y}
        Q${x},${y + sag + h} ${x - len / 2},${y} Z`,
    color: ["#ffffff", "#fef9c3", "#fde68a"][i % 3],
    peak: 0.45 + j1 * 0.5,
    dur: 1.3 + j2 * 2.4,                     // 明滅
    delay: j3 * 3,
    bob: 0.6 + depth * 1.8,                  // 波に乗る上下動(手前ほど大きい)
    bobDur: 2.9 + j2 * 3.2,
    bobDelay: -(j1 * 4),
  };
});

<div className="glitter-stage">
  <div className="glitter-sun" />
  <svg viewBox="0 0 400 120" className="glitter-sea" preserveAspectRatio="none">
    {seaStripes.map((s, i) => (
      <path key={i} className="sea-stripe" d={s.d} fill={s.color}
        style={{
          filter: `blur(${s.blur}px)`,
          "--samp": `${s.swayAmp}px`, "--dur": `${s.swayDur}s`,
          animationDelay: `${s.swayDelay}s`,
        }} />
    ))}
  </svg>
  <div className="glitter-horizon" />
  <div className="glitter-band" />
  <svg viewBox="0 0 400 120" className="glitter-lines" preserveAspectRatio="none">
    {glints.map((g, i) => (
      <path key={i} d={g.d} fill={g.color}
        style={{
          "--peak": g.peak, "--bob": `${g.bob}px`,
          animationDuration: `${g.dur}s, ${g.bobDur}s`,
          animationDelay: `${g.delay}s, ${g.bobDelay}s`,
        }} />
    ))}
  </svg>
</div>
css
.glitter-stage {
  position: relative;
  height: 180px;
  border-radius: 8px;
  overflow: hidden;
  /* 上1/3が夕方の空。海はストライプのSVGで描く */
  background: linear-gradient(180deg, #fef3c7 0%, #fcd34d 31%, #0369a1 33%, #0369a1 100%);
}
/* 海のストライプ。境界の波がゆっくり横に揺れる */
.glitter-sea { position: absolute; top: 33%; left: 0; width: 100%; height: 67%; }
.sea-stripe { animation: stripeSway var(--dur) ease-in-out infinite alternate; }
@keyframes stripeSway {
  from { transform: translateX(calc(var(--samp) * -1)); }
  to   { transform: translateX(var(--samp)); }
}
.glitter-sun {
  position: absolute;
  top: 14px; left: 50%;
  width: 30px; height: 30px; margin-left: -15px;
  border-radius: 9999px;
  background: #fde68a;
  filter: blur(2px);
  box-shadow: 0 0 22px 8px rgba(253, 230, 138, 0.55);
}
.glitter-horizon {
  position: absolute;
  top: 33%; left: 0; right: 0;
  height: 1px;
  background: rgba(255, 255, 255, 0.5);
}
/* 太陽の反射の帯。overlay合成でゆっくり明滅 */
.glitter-band {
  position: absolute;
  top: 33%; bottom: 0; left: 50%;
  width: 44px; margin-left: -22px;
  background: linear-gradient(180deg, rgba(253,230,138,0.8), rgba(253,230,138,0.08));
  mix-blend-mode: overlay;
  filter: blur(2px);
  animation: bandPulse 5s ease-in-out infinite alternate;
}
@keyframes bandPulse {
  from { opacity: .55; }
  to   { opacity: 1; }
}
.glitter-lines { position: absolute; top: 33%; left: 0; width: 100%; height: 67%; }
/* レンズ形(fill)のきらめき。明滅(glint)と波に乗る上下動(glintBob)を別アニメで合成 */
.glitter-lines path {
  opacity: var(--peak);
  animation-name: glint, glintBob;
  animation-timing-function: ease-in-out, ease-in-out;
  animation-iteration-count: infinite, infinite;
  animation-direction: normal, alternate;
}
@keyframes glint {
  0%, 100% { opacity: 0; }
  50%      { opacity: var(--peak); }
}
@keyframes glintBob {
  from { transform: translateY(calc(var(--bob) * -1)); }
  to   { transform: translateY(var(--bob)); }
}
📖 関連: SVG

よくある質問

写真素材と抽象表現、どちらを使うべき?

実物の質感が必要なら写真、世界観の統一・軽量さ・他要素との馴染みを重視するなら抽象表現が向きます。写真の上に本ページの表現(光芒・きらめき)を重ねるハイブリッドも効果的で、写真だけよりも「動きのある海」を演出できます。

波のアニメーションは重くなりませんか?

SVG pathのtransform移動は軽量ですが、feTurbulenceフィルターはGPU負荷が高めです。フィルターは最前面の1層だけに絞る、モバイルではフィルターを外す(メディアクエリ)、画面外では停止する(Intersection Observer)などの工夫で実用範囲に収まります。

「海らしさ」を一番手軽に出すには?

1つだけ選ぶなら「重なる波」をセクション境界(区切り)に使うのが最も手軽で効果的です。ページ下部やフッター上に波を1セット置くだけで、サイト全体が海の世界観になります。

AIに頼むとき、複数の表現を組み合わせるコツは?

「背景は深海の光芒、その上に泡を5個ゆっくり上昇させる」のように、レイヤー構造(背景→中景→アクセント)を明示して指示すると破綻しにくいです。一度に全部頼まず、まず背景、次に泡、と段階的に重ねるのも有効です。