無限ループローダー

SVGの∞パス上をグラデーションの発光線がstroke-dashで滑らかに周回するローダー。ブランド感のある待機演出として印象的に使えます。

#svg#css#animation

ライブデモ

使用例(お題: SaaS FlowDesk)

この技法を「SaaS FlowDesk」というテーマのダミーサイトで実際に使った例です。

HTML
<!-- FlowDesk:ワークスペース準備中スプラッシュ。∞ローダーが周回→本編CTAへ -->
<div class="fd-stage" id="fdStage">

  <!-- 本編(背面に常駐) -->
  <main class="fd-ready">
    <span class="fd-ready__logo"><span class="fd-ready__mark">◆</span> FlowDesk</span>
    <h1 class="fd-ready__title">ワークスペースの<br>準備ができました。</h1>
    <p class="fd-ready__lead">チームのタスクとダッシュボードを同期しました。</p>
    <a class="fd-ready__btn" href="#">ダッシュボードを開く</a>
  </main>

  <!-- ローディングオーバーレイ -->
  <div class="fd-load" id="fdLoad">
    <!-- ∞パスを発光線が周回する -->
    <svg class="fd-inf" viewBox="0 0 200 100" aria-label="読み込み中">
      <defs>
        <linearGradient id="fdGrad" x1="0" y1="0" x2="1" y2="0">
          <stop offset="0" stop-color="#4f7cff" stop-opacity="0"/>
          <stop offset="0.5" stop-color="#8fb0ff"/>
          <stop offset="1" stop-color="#4f7cff" stop-opacity="0"/>
        </linearGradient>
      </defs>
      <path class="fd-inf__bg"
        d="M40,50 C40,25 70,25 100,50 C130,75 160,75 160,50 C160,25 130,25 100,50 C70,75 40,75 40,50 Z"/>
      <path class="fd-inf__line"
        d="M40,50 C40,25 70,25 100,50 C130,75 160,75 160,50 C160,25 130,25 100,50 C70,75 40,75 40,50 Z"/>
    </svg>
    <p class="fd-load__name"><span class="fd-load__mark">◆</span> FlowDesk</p>
    <p class="fd-load__sub">ワークスペースを準備しています…</p>
  </div>

</div>
CSS
/* FlowDesk:∞ ローダー → 本編CTA */
:root {
  --navy: #0f1b34;
  --navy2: #16264a;
  --blue: #4f7cff;
  --muted: #9fb0d4;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  height: 400px;
  font-family: "Segoe UI", "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
  overflow: hidden;
}

.fd-stage { position: relative; height: 400px; background: var(--navy); }

/* 本編 */
.fd-ready {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 36px;
  color: #fff;
  background:
    radial-gradient(700px 300px at 80% -10%, rgba(79,124,255,0.28), transparent 60%),
    var(--navy);
}
.fd-ready__logo { font-size: 14px; font-weight: 700; color: var(--muted); margin-bottom: 14px; }
.fd-ready__mark { color: var(--blue); }
.fd-ready__title { margin: 0 0 12px; font-size: 28px; line-height: 1.4; font-weight: 700; }
.fd-ready__lead { margin: 0 0 22px; font-size: 13px; color: var(--muted); line-height: 1.7; }
.fd-ready__btn {
  align-self: flex-start;
  padding: 12px 24px;
  border-radius: 10px;
  background: var(--blue);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
  box-shadow: 0 10px 26px rgba(79,124,255,0.45);
}

/* ローディングオーバーレイ */
.fd-load {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: var(--navy);
  transition: opacity 0.6s ease, visibility 0.6s ease;
}
.fd-load.is-done { opacity: 0; visibility: hidden; }

/* ∞ SVG */
.fd-inf { width: 200px; height: 100px; }
.fd-inf__bg {
  fill: none;
  stroke: rgba(255,255,255,0.08);
  stroke-width: 5;
}
.fd-inf__line {
  fill: none;
  stroke: url(#fdGrad);
  stroke-width: 5;
  stroke-linecap: round;
  /* 発光線がパス上を滑らかに周回 */
  stroke-dasharray: 90 360;
  filter: drop-shadow(0 0 6px rgba(79,124,255,0.8));
  animation: fd-orbit 2s linear infinite;
}
@keyframes fd-orbit { to { stroke-dashoffset: -450; } }

.fd-load__name {
  margin: 10px 0 0;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #fff;
}
.fd-load__mark { color: var(--blue); }
.fd-load__sub { margin: 6px 0 0; font-size: 11px; color: var(--muted); letter-spacing: 0.06em; }

@media (prefers-reduced-motion: reduce) {
  .fd-inf__line { animation: none; }
  .fd-load { transition: none; }
}
JavaScript
// FlowDesk:∞ ローダーをしばらく見せてから本編へ(疑似準備・ループ)
const load = document.getElementById('fdLoad');

function run() {
  if (!load) return;
  load.classList.remove('is-done');
  // 2.4秒準備 → オーバーレイをフェードアウトして本編表示
  setTimeout(() => load.classList.add('is-done'), 2400);
  // 完了から少し置いて再ループ
  setTimeout(run, 5200);
}

// 初回起動
run();

コード

HTML
<!-- 無限ループローダー: SVGの∞パス上を光のドットが滑らかに周回する -->
<div class="if-stage">
  <div class="if-box">
    <svg class="if-svg" viewBox="0 0 200 100" aria-hidden="true">
      <defs>
        <linearGradient id="ifGrad" x1="0%" y1="0%" x2="100%" y2="0%">
          <stop offset="0%" stop-color="#22d3ee"/>
          <stop offset="50%" stop-color="#a78bfa"/>
          <stop offset="100%" stop-color="#f472b6"/>
        </linearGradient>
      </defs>
      <!-- ∞ の軌道(薄いガイド) -->
      <path class="if-track"
        d="M100,50 C100,20 60,20 50,50 C40,80 0,80 0,50 C0,20 40,20 50,50 C60,80 100,80 100,50 C100,20 140,20 150,50 C160,80 200,80 200,50 C200,20 160,20 150,50 C140,80 100,80 100,50 Z"/>
      <!-- なぞって描く発光線(同じパスを直接描画) -->
      <path class="if-glow"
        d="M100,50 C100,20 60,20 50,50 C40,80 0,80 0,50 C0,20 40,20 50,50 C60,80 100,80 100,50 C100,20 140,20 150,50 C160,80 200,80 200,50 C200,20 160,20 150,50 C140,80 100,80 100,50 Z"/>
    </svg>
    <p class="if-label">Loading<span class="if-ell">…</span></p>
  </div>
</div>
CSS
:root {
  --bg: #0b0f1e;
  --track: rgba(255, 255, 255, .07);
  --txt: #cdd6ff;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  place-items: center;
  font-family: "Segoe UI", system-ui, sans-serif;
  background:
    radial-gradient(800px 500px at 50% 50%, #161d3d 0%, transparent 60%),
    var(--bg);
  color: var(--txt);
}
.if-box {
  display: grid;
  justify-items: center;
  gap: 18px;
  padding: 24px;
}
.if-svg { width: 240px; height: 120px; overflow: visible; }
.if-track {
  fill: none;
  stroke: var(--track);
  stroke-width: 4;
}
/* 発光線: dash を流して∞をなぞる動き */
.if-glow {
  fill: none;
  stroke: url(#ifGrad);
  stroke-width: 4;
  stroke-linecap: round;
  /* パス長 ≒ 590。dash+gap を 1周期=590 に合わせ、
     offset を 1周分(-590)動かして継ぎ目なくループさせる */
  stroke-dasharray: 110 480;
  filter: drop-shadow(0 0 5px rgba(167, 139, 250, .8));
  animation: if-run 2.6s linear infinite;
}
@keyframes if-run {
  to { stroke-dashoffset: -590; }
}
.if-label {
  margin: 0;
  font-size: 13px;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: rgba(205, 214, 255, .65);
}
/* 末尾の点が順に現れる */
.if-ell { display: inline-block; width: 1.4em; text-align: left; animation: if-dots 1.4s steps(4) infinite; }
@keyframes if-dots {
  0% { clip-path: inset(0 100% 0 0); }
  100% { clip-path: inset(0 0 0 0); }
}

@media (prefers-reduced-motion: reduce) {
  .if-glow { animation-duration: 8s; }
  .if-ell { animation: none; }
}
JavaScript
// このデモは SVG パスと CSS アニメーションのみで動作するため JS は不要

🤖 AIエージェント用プロンプト

このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「無限ループローダー」の効果を追加してください。

# 追加してほしい効果
無限ループローダー(ローダー & スケルトン)
SVGの∞パス上をグラデーションの発光線がstroke-dashで滑らかに周回するローダー。ブランド感のある待機演出として印象的に使えます。

# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】

# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- 無限ループローダー: SVGの∞パス上を光のドットが滑らかに周回する -->
<div class="if-stage">
  <div class="if-box">
    <svg class="if-svg" viewBox="0 0 200 100" aria-hidden="true">
      <defs>
        <linearGradient id="ifGrad" x1="0%" y1="0%" x2="100%" y2="0%">
          <stop offset="0%" stop-color="#22d3ee"/>
          <stop offset="50%" stop-color="#a78bfa"/>
          <stop offset="100%" stop-color="#f472b6"/>
        </linearGradient>
      </defs>
      <!-- ∞ の軌道(薄いガイド) -->
      <path class="if-track"
        d="M100,50 C100,20 60,20 50,50 C40,80 0,80 0,50 C0,20 40,20 50,50 C60,80 100,80 100,50 C100,20 140,20 150,50 C160,80 200,80 200,50 C200,20 160,20 150,50 C140,80 100,80 100,50 Z"/>
      <!-- なぞって描く発光線(同じパスを直接描画) -->
      <path class="if-glow"
        d="M100,50 C100,20 60,20 50,50 C40,80 0,80 0,50 C0,20 40,20 50,50 C60,80 100,80 100,50 C100,20 140,20 150,50 C160,80 200,80 200,50 C200,20 160,20 150,50 C140,80 100,80 100,50 Z"/>
    </svg>
    <p class="if-label">Loading<span class="if-ell">…</span></p>
  </div>
</div>

【CSS】
:root {
  --bg: #0b0f1e;
  --track: rgba(255, 255, 255, .07);
  --txt: #cdd6ff;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  place-items: center;
  font-family: "Segoe UI", system-ui, sans-serif;
  background:
    radial-gradient(800px 500px at 50% 50%, #161d3d 0%, transparent 60%),
    var(--bg);
  color: var(--txt);
}
.if-box {
  display: grid;
  justify-items: center;
  gap: 18px;
  padding: 24px;
}
.if-svg { width: 240px; height: 120px; overflow: visible; }
.if-track {
  fill: none;
  stroke: var(--track);
  stroke-width: 4;
}
/* 発光線: dash を流して∞をなぞる動き */
.if-glow {
  fill: none;
  stroke: url(#ifGrad);
  stroke-width: 4;
  stroke-linecap: round;
  /* パス長 ≒ 590。dash+gap を 1周期=590 に合わせ、
     offset を 1周分(-590)動かして継ぎ目なくループさせる */
  stroke-dasharray: 110 480;
  filter: drop-shadow(0 0 5px rgba(167, 139, 250, .8));
  animation: if-run 2.6s linear infinite;
}
@keyframes if-run {
  to { stroke-dashoffset: -590; }
}
.if-label {
  margin: 0;
  font-size: 13px;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: rgba(205, 214, 255, .65);
}
/* 末尾の点が順に現れる */
.if-ell { display: inline-block; width: 1.4em; text-align: left; animation: if-dots 1.4s steps(4) infinite; }
@keyframes if-dots {
  0% { clip-path: inset(0 100% 0 0); }
  100% { clip-path: inset(0 0 0 0); }
}

@media (prefers-reduced-motion: reduce) {
  .if-glow { animation-duration: 8s; }
  .if-ell { animation: none; }
}

【JavaScript】
// このデモは SVG パスと CSS アニメーションのみで動作するため JS は不要

# 外部ライブラリ
なし(追加ライブラリ不要)

# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。