各種スピナー集

リング・デュアル・オービット・バー・パルス・キューブの6種を純CSSで実装したスピナー詰め合わせ。用途に合うローディング表現をすぐ選べます。

#css#animation#spinner

ライブデモ

使用例(お題: SaaS FlowDesk)

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

HTML
<!-- FlowDesk ダッシュボード:各ウィジェットがスピナーで読み込み→データ表示 -->
<div class="fd-dash">
  <header class="fd-dash__bar">
    <span class="fd-dash__logo"><span class="fd-dash__mark">◆</span> FlowDesk</span>
    <span class="fd-dash__sync" id="fdSync">同期中…</span>
  </header>

  <div class="fd-grid" id="fdGrid" data-state="loading">
    <!-- 各カードはスピナー→数値へ。スピナー種類を散らす -->
    <article class="fd-w">
      <p class="fd-w__label">アクティブユーザー</p>
      <div class="fd-w__body">
        <div class="sp sp-ring" aria-label="読み込み中"></div>
        <div class="fd-w__data"><b>1,284</b><span class="fd-up">+12%</span></div>
      </div>
    </article>

    <article class="fd-w">
      <p class="fd-w__label">完了タスク</p>
      <div class="fd-w__body">
        <div class="sp sp-dual" aria-label="読み込み中"></div>
        <div class="fd-w__data"><b>356</b><span class="fd-up">+8%</span></div>
      </div>
    </article>

    <article class="fd-w">
      <p class="fd-w__label">稼働率</p>
      <div class="fd-w__body">
        <div class="sp sp-bars" aria-label="読み込み中"><i></i><i></i><i></i><i></i></div>
        <div class="fd-w__data"><b>99.9%</b><span class="fd-up">SLA</span></div>
      </div>
    </article>

    <article class="fd-w">
      <p class="fd-w__label">月次収益</p>
      <div class="fd-w__body">
        <div class="sp sp-pulse" aria-label="読み込み中"></div>
        <div class="fd-w__data"><b>¥4.2M</b><span class="fd-up">+19%</span></div>
      </div>
    </article>
  </div>
</div>
CSS
/* FlowDesk ダッシュボード:スピナー集(ウィジェット読み込み) */
:root {
  --navy: #0f1b34;
  --navy2: #16264a;
  --blue: #4f7cff;
  --line: rgba(255,255,255,0.08);
  --muted: #9fb0d4;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  height: 400px;
  display: grid;
  place-items: center;
  font-family: "Segoe UI", "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
  background: var(--navy);
  color: #fff;
  overflow: hidden;
}

.fd-dash { width: 360px; }

.fd-dash__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
.fd-dash__logo { font-size: 15px; font-weight: 700; letter-spacing: 0.04em; }
.fd-dash__mark { color: var(--blue); margin-right: 4px; }
.fd-dash__sync { font-size: 11px; color: var(--blue); }
.fd-dash__sync.is-done { color: #4ade80; }

.fd-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.fd-w {
  background: var(--navy2);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 14px;
}
.fd-w__label { margin: 0 0 12px; font-size: 11px; color: var(--muted); }
.fd-w__body { min-height: 38px; display: flex; align-items: center; }

/* 状態でスピナー/データを切替 */
.fd-grid[data-state="loading"] .fd-w__data { display: none; }
.fd-grid[data-state="ready"] .sp { display: none; }

.fd-w__data { display: flex; align-items: baseline; gap: 8px; animation: fd-fade 0.4s ease both; }
.fd-w__data b { font-size: 24px; font-weight: 700; }
.fd-up { font-size: 11px; color: #4ade80; }
@keyframes fd-fade { from { opacity: 0; transform: translateY(4px); } }

/* === スピナー各種(純CSS) === */
/* リング */
.sp-ring {
  width: 28px; height: 28px;
  border: 3px solid rgba(79,124,255,0.25);
  border-top-color: var(--blue);
  border-radius: 50%;
  animation: sp-spin 0.8s linear infinite;
}
/* デュアルリング */
.sp-dual {
  width: 28px; height: 28px;
  border: 3px solid transparent;
  border-top-color: var(--blue);
  border-bottom-color: #8fa8ff;
  border-radius: 50%;
  animation: sp-spin 0.9s linear infinite;
}
/* バー */
.sp-bars { display: flex; gap: 4px; height: 28px; align-items: center; }
.sp-bars i {
  width: 4px; height: 22px;
  background: var(--blue);
  border-radius: 2px;
  animation: sp-bar 1s ease-in-out infinite;
}
.sp-bars i:nth-child(2) { animation-delay: 0.15s; }
.sp-bars i:nth-child(3) { animation-delay: 0.3s; }
.sp-bars i:nth-child(4) { animation-delay: 0.45s; }
/* パルス */
.sp-pulse {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--blue);
  animation: sp-pulse 1s ease-in-out infinite;
}

@keyframes sp-spin { to { transform: rotate(360deg); } }
@keyframes sp-bar { 0%, 100% { transform: scaleY(0.4); } 50% { transform: scaleY(1); } }
@keyframes sp-pulse { 0%, 100% { transform: scale(0.6); opacity: 0.5; } 50% { transform: scale(1); opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .sp-ring, .sp-dual, .sp-bars i, .sp-pulse { animation: none; }
  .fd-w__data { animation: none; }
}
JavaScript
// FlowDesk ダッシュボード:スピナー → 数値表示(疑似同期・自動ループ)
const grid = document.getElementById('fdGrid');
const sync = document.getElementById('fdSync');

function loadDash() {
  if (!grid) return;
  grid.dataset.state = 'loading';
  if (sync) { sync.textContent = '同期中…'; sync.classList.remove('is-done'); }
  // 1.7秒で各ウィジェットのデータ取得完了
  setTimeout(() => {
    grid.dataset.state = 'ready';
    if (sync) { sync.textContent = '最新です'; sync.classList.add('is-done'); }
  }, 1700);
}

// 完了後しばらくして再同期(ループ)
setInterval(() => {
  if (grid && grid.dataset.state === 'ready') loadDash();
}, 4400);

// 初回起動
loadDash();

コード

HTML
<!-- 各種スピナー集: 純CSSで作る6種類のローディングスピナー -->
<div class="sp-stage">
  <div class="sp-grid">
    <figure class="sp-item">
      <!-- 1. リング(回転する円弧) -->
      <div class="sp-ring"></div>
      <figcaption>Ring</figcaption>
    </figure>
    <figure class="sp-item">
      <!-- 2. デュアルリング(二重円) -->
      <div class="sp-dual"></div>
      <figcaption>Dual</figcaption>
    </figure>
    <figure class="sp-item">
      <!-- 3. オービット(軌道を回る点) -->
      <div class="sp-orbit"><span></span><span></span><span></span></div>
      <figcaption>Orbit</figcaption>
    </figure>
    <figure class="sp-item">
      <!-- 4. バー(伸縮する縦棒) -->
      <div class="sp-bars"><i></i><i></i><i></i><i></i><i></i></div>
      <figcaption>Bars</figcaption>
    </figure>
    <figure class="sp-item">
      <!-- 5. パルスリング(広がる波) -->
      <div class="sp-pulse"></div>
      <figcaption>Pulse</figcaption>
    </figure>
    <figure class="sp-item">
      <!-- 6. グリッド(点滅する格子) -->
      <div class="sp-cube"><span></span><span></span><span></span><span></span></div>
      <figcaption>Cube</figcaption>
    </figure>
  </div>
</div>
CSS
:root {
  --bg: #0d1117;
  --c1: #5eead4;
  --c2: #818cf8;
  --c3: #f472b6;
  --track: rgba(255, 255, 255, .12);
  --txt: #c9d1e8;
}
* { 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(900px 500px at 80% 120%, #16233a 0%, transparent 55%),
    radial-gradient(700px 400px at 10% -10%, #1c1733 0%, transparent 55%),
    var(--bg);
  color: var(--txt);
}
.sp-stage { padding: 26px; }
.sp-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px 30px;
}
.sp-item {
  margin: 0;
  display: grid;
  justify-items: center;
  gap: 12px;
}
.sp-item figcaption {
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(201, 209, 232, .6);
}
.sp-item > :first-child { width: 52px; height: 52px; position: relative; }

/* 1. リング */
.sp-ring {
  border-radius: 50%;
  border: 5px solid var(--track);
  border-top-color: var(--c1);
  animation: sp-spin .9s linear infinite;
}
/* 2. デュアルリング */
.sp-dual {
  border-radius: 50%;
  border: 5px solid transparent;
  border-top-color: var(--c2);
  border-bottom-color: var(--c3);
  animation: sp-spin 1.1s linear infinite;
}
/* 3. オービット */
.sp-orbit span {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 3px solid transparent;
  border-top-color: var(--c1);
  animation: sp-spin 1.4s cubic-bezier(.5, 0, .5, 1) infinite;
}
.sp-orbit span:nth-child(2) { inset: 8px; border-top-color: var(--c2); animation-duration: 1.1s; }
.sp-orbit span:nth-child(3) { inset: 16px; border-top-color: var(--c3); animation-duration: .8s; }
/* 4. バー */
.sp-bars { display: flex; align-items: center; gap: 5px; }
.sp-bars i {
  width: 6px; height: 100%;
  border-radius: 3px;
  background: var(--c2);
  animation: sp-stretch 1s ease-in-out infinite;
}
.sp-bars i:nth-child(2) { animation-delay: .1s; }
.sp-bars i:nth-child(3) { animation-delay: .2s; background: var(--c1); }
.sp-bars i:nth-child(4) { animation-delay: .3s; }
.sp-bars i:nth-child(5) { animation-delay: .4s; background: var(--c3); }
/* 5. パルスリング */
.sp-pulse {
  border-radius: 50%;
  background: radial-gradient(circle, var(--c3) 30%, transparent 32%);
  box-shadow: 0 0 0 0 rgba(244, 114, 182, .5);
  animation: sp-pulse 1.3s ease-out infinite;
}
/* 6. キューブグリッド */
.sp-cube {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}
.sp-cube span {
  border-radius: 5px;
  background: var(--c1);
  animation: sp-scale 1.2s ease-in-out infinite;
}
.sp-cube span:nth-child(2) { background: var(--c2); animation-delay: .15s; }
.sp-cube span:nth-child(3) { background: var(--c3); animation-delay: .45s; }
.sp-cube span:nth-child(4) { background: var(--c2); animation-delay: .3s; }

@keyframes sp-spin { to { transform: rotate(360deg); } }
@keyframes sp-stretch { 0%, 100% { transform: scaleY(.35); opacity: .6; } 50% { transform: scaleY(1); opacity: 1; } }
@keyframes sp-pulse {
  0% { transform: scale(.6); box-shadow: 0 0 0 0 rgba(244, 114, 182, .5); }
  70% { transform: scale(1); box-shadow: 0 0 0 18px rgba(244, 114, 182, 0); }
  100% { transform: scale(.6); box-shadow: 0 0 0 0 rgba(244, 114, 182, 0); }
}
@keyframes sp-scale { 0%, 70%, 100% { transform: scale(1); opacity: 1; } 35% { transform: scale(.5); opacity: .4; } }

@media (prefers-reduced-motion: reduce) {
  .sp-ring, .sp-dual, .sp-orbit span, .sp-bars i, .sp-pulse, .sp-cube span { animation-duration: 3s; }
}
JavaScript
// このデモは純CSSアニメーションのみで動作するため JS は不要

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

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

# 追加してほしい効果
各種スピナー集(ローダー & スケルトン)
リング・デュアル・オービット・バー・パルス・キューブの6種を純CSSで実装したスピナー詰め合わせ。用途に合うローディング表現をすぐ選べます。

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

# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- 各種スピナー集: 純CSSで作る6種類のローディングスピナー -->
<div class="sp-stage">
  <div class="sp-grid">
    <figure class="sp-item">
      <!-- 1. リング(回転する円弧) -->
      <div class="sp-ring"></div>
      <figcaption>Ring</figcaption>
    </figure>
    <figure class="sp-item">
      <!-- 2. デュアルリング(二重円) -->
      <div class="sp-dual"></div>
      <figcaption>Dual</figcaption>
    </figure>
    <figure class="sp-item">
      <!-- 3. オービット(軌道を回る点) -->
      <div class="sp-orbit"><span></span><span></span><span></span></div>
      <figcaption>Orbit</figcaption>
    </figure>
    <figure class="sp-item">
      <!-- 4. バー(伸縮する縦棒) -->
      <div class="sp-bars"><i></i><i></i><i></i><i></i><i></i></div>
      <figcaption>Bars</figcaption>
    </figure>
    <figure class="sp-item">
      <!-- 5. パルスリング(広がる波) -->
      <div class="sp-pulse"></div>
      <figcaption>Pulse</figcaption>
    </figure>
    <figure class="sp-item">
      <!-- 6. グリッド(点滅する格子) -->
      <div class="sp-cube"><span></span><span></span><span></span><span></span></div>
      <figcaption>Cube</figcaption>
    </figure>
  </div>
</div>

【CSS】
:root {
  --bg: #0d1117;
  --c1: #5eead4;
  --c2: #818cf8;
  --c3: #f472b6;
  --track: rgba(255, 255, 255, .12);
  --txt: #c9d1e8;
}
* { 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(900px 500px at 80% 120%, #16233a 0%, transparent 55%),
    radial-gradient(700px 400px at 10% -10%, #1c1733 0%, transparent 55%),
    var(--bg);
  color: var(--txt);
}
.sp-stage { padding: 26px; }
.sp-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px 30px;
}
.sp-item {
  margin: 0;
  display: grid;
  justify-items: center;
  gap: 12px;
}
.sp-item figcaption {
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(201, 209, 232, .6);
}
.sp-item > :first-child { width: 52px; height: 52px; position: relative; }

/* 1. リング */
.sp-ring {
  border-radius: 50%;
  border: 5px solid var(--track);
  border-top-color: var(--c1);
  animation: sp-spin .9s linear infinite;
}
/* 2. デュアルリング */
.sp-dual {
  border-radius: 50%;
  border: 5px solid transparent;
  border-top-color: var(--c2);
  border-bottom-color: var(--c3);
  animation: sp-spin 1.1s linear infinite;
}
/* 3. オービット */
.sp-orbit span {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 3px solid transparent;
  border-top-color: var(--c1);
  animation: sp-spin 1.4s cubic-bezier(.5, 0, .5, 1) infinite;
}
.sp-orbit span:nth-child(2) { inset: 8px; border-top-color: var(--c2); animation-duration: 1.1s; }
.sp-orbit span:nth-child(3) { inset: 16px; border-top-color: var(--c3); animation-duration: .8s; }
/* 4. バー */
.sp-bars { display: flex; align-items: center; gap: 5px; }
.sp-bars i {
  width: 6px; height: 100%;
  border-radius: 3px;
  background: var(--c2);
  animation: sp-stretch 1s ease-in-out infinite;
}
.sp-bars i:nth-child(2) { animation-delay: .1s; }
.sp-bars i:nth-child(3) { animation-delay: .2s; background: var(--c1); }
.sp-bars i:nth-child(4) { animation-delay: .3s; }
.sp-bars i:nth-child(5) { animation-delay: .4s; background: var(--c3); }
/* 5. パルスリング */
.sp-pulse {
  border-radius: 50%;
  background: radial-gradient(circle, var(--c3) 30%, transparent 32%);
  box-shadow: 0 0 0 0 rgba(244, 114, 182, .5);
  animation: sp-pulse 1.3s ease-out infinite;
}
/* 6. キューブグリッド */
.sp-cube {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}
.sp-cube span {
  border-radius: 5px;
  background: var(--c1);
  animation: sp-scale 1.2s ease-in-out infinite;
}
.sp-cube span:nth-child(2) { background: var(--c2); animation-delay: .15s; }
.sp-cube span:nth-child(3) { background: var(--c3); animation-delay: .45s; }
.sp-cube span:nth-child(4) { background: var(--c2); animation-delay: .3s; }

@keyframes sp-spin { to { transform: rotate(360deg); } }
@keyframes sp-stretch { 0%, 100% { transform: scaleY(.35); opacity: .6; } 50% { transform: scaleY(1); opacity: 1; } }
@keyframes sp-pulse {
  0% { transform: scale(.6); box-shadow: 0 0 0 0 rgba(244, 114, 182, .5); }
  70% { transform: scale(1); box-shadow: 0 0 0 18px rgba(244, 114, 182, 0); }
  100% { transform: scale(.6); box-shadow: 0 0 0 0 rgba(244, 114, 182, 0); }
}
@keyframes sp-scale { 0%, 70%, 100% { transform: scale(1); opacity: 1; } 35% { transform: scale(.5); opacity: .4; } }

@media (prefers-reduced-motion: reduce) {
  .sp-ring, .sp-dual, .sp-orbit span, .sp-bars i, .sp-pulse, .sp-cube span { animation-duration: 3s; }
}

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

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

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