ドット/グリッド背景

CSSのドット格子にマウス追従のスポットライトを重ねた背景。マスクで照らした部分だけドットを濃く見せます。ダッシュボード向け。

#css#javascript#interactive

ライブデモ

使用例(お題: SaaS FlowDesk)

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

HTML
<!-- FlowDesk:ドット格子+スポットライトのインテグレーション一覧 -->
<section class="fd-stage" id="fdStage">
  <!-- ★主役:ドット格子とマウス追従スポットライト -->
  <div class="fd-dots" aria-hidden="true"></div>
  <div class="fd-spot" id="fdSpot" aria-hidden="true"></div>

  <div class="fd-inner">
    <header class="fd-head">
      <h1 class="fd-title">100+ の連携を、ワンクリックで</h1>
      <p class="fd-sub">使っているツールをそのまま FlowDesk に接続。マウスを動かすとドットが灯ります。</p>
    </header>

    <div class="fd-apps">
      <div class="fd-app"><span class="fd-app__ico" style="--c:#4f7cff">◆</span>カレンダー</div>
      <div class="fd-app"><span class="fd-app__ico" style="--c:#22c55e">▣</span>スプレッド</div>
      <div class="fd-app"><span class="fd-app__ico" style="--c:#f59e0b">◉</span>チャット</div>
      <div class="fd-app"><span class="fd-app__ico" style="--c:#ec4899">✦</span>ストレージ</div>
      <div class="fd-app"><span class="fd-app__ico" style="--c:#8b5cf6">⬡</span>CRM</div>
      <div class="fd-app"><span class="fd-app__ico" style="--c:#06b6d4">⬢</span>分析</div>
    </div>
  </div>
</section>
CSS
/* FlowDesk:紺地のドット格子をスポットライトで照らす連携一覧 */
* { box-sizing: border-box; margin: 0; padding: 0; }

.fd-stage {
  position: relative;
  min-height: 400px;
  height: 400px;
  overflow: hidden;
  background: #0f1b34;
  color: #fff;
  font-family: "Segoe UI", "Hiragino Sans", system-ui, sans-serif;
}

/* ★主役:CSSのドット格子(全面に薄く敷く) */
.fd-dots {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: radial-gradient(rgba(150,180,255,0.5) 1.4px, transparent 1.4px);
  background-size: 22px 22px;
  opacity: 0.35;
}

/* ★スポットライト:マウス位置のドットだけ明るく見せるマスク層 */
.fd-spot {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image: radial-gradient(#7fa0ff 1.6px, transparent 1.6px);
  background-size: 22px 22px;
  /* スポット内だけドットを濃く表示 */
  -webkit-mask-image: radial-gradient(180px circle at var(--mx, -200px) var(--my, -200px), #000 0%, transparent 70%);
          mask-image: radial-gradient(180px circle at var(--mx, -200px) var(--my, -200px), #000 0%, transparent 70%);
}

.fd-inner {
  position: relative;
  z-index: 2;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 34px;
}
.fd-title {
  font-size: 28px;
  font-weight: 800;
  letter-spacing: 0.01em;
  text-shadow: 0 4px 20px rgba(0,0,0,0.5);
}
.fd-sub {
  margin-top: 10px;
  font-size: 13px;
  line-height: 1.7;
  color: rgba(255,255,255,0.82);
  max-width: 420px;
}

.fd-apps {
  margin-top: 22px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  max-width: 520px;
}
.fd-app {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  font-weight: 600;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.12);
  transition: transform 0.2s ease, border-color 0.2s ease;
}
.fd-app:hover { transform: translateY(-2px); border-color: rgba(127,160,255,0.5); }
.fd-app__ico {
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--c) 22%, transparent);
  color: var(--c);
  font-size: 14px;
}

@media (prefers-reduced-motion: reduce) {
  .fd-app { transition: none; }
}
JavaScript
// マウス位置をCSS変数に渡し、ドット格子のスポットライトを追従させる
(() => {
  const stage = document.getElementById("fdStage");
  const spot = document.getElementById("fdSpot");
  if (!stage || !spot) return; // null安全

  // ステージ内の相対座標をスポットへ反映
  stage.addEventListener("pointermove", (e) => {
    const rect = stage.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    spot.style.setProperty("--mx", x + "px");
    spot.style.setProperty("--my", y + "px");
  });

  // 離れたらスポットを画面外へ
  stage.addEventListener("pointerleave", () => {
    spot.style.setProperty("--mx", "-200px");
    spot.style.setProperty("--my", "-200px");
  });
})();

コード

HTML
<!-- ドット/グリッド背景: CSSのドット格子にスポットライトを追従させる -->
<div class="dg-stage" id="dgStage">
  <div class="dg-dots"></div>
  <div class="dg-glow" id="dgGlow"></div>
  <div class="dg-content">
    <h1 class="dg-title">Dot Grid</h1>
    <p class="dg-sub">マウスに追従するスポットライトでドット格子を照らす、ダッシュボード向けの背景です。</p>
  </div>
</div>
CSS
/* ドット格子 + マウス追従グロー */
* { box-sizing: border-box; margin: 0; padding: 0; }

.dg-stage {
  position: relative;
  min-height: 360px;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: #0b0e16;
  font-family: "Segoe UI", "Hiragino Sans", system-ui, sans-serif;
  --mx: 50%;
  --my: 50%;
}

/* ドット格子: 繰り返し radial-gradient で点を打つ */
.dg-dots {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(120, 150, 255, 0.35) 1.4px, transparent 1.5px);
  background-size: 26px 26px;
  /* マウス周辺だけドットを濃く見せるマスク */
  -webkit-mask-image: radial-gradient(240px 240px at var(--mx) var(--my), #000 0%, rgba(0,0,0,0.25) 60%, transparent 100%);
  mask-image: radial-gradient(240px 240px at var(--mx) var(--my), #000 0%, rgba(0,0,0,0.25) 60%, transparent 100%);
}

/* マウス位置に淡い光 */
.dg-glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(300px 300px at var(--mx) var(--my), rgba(99, 102, 241, 0.22), transparent 70%);
  pointer-events: none;
  transition: background 0.08s linear;
}

.dg-content {
  position: relative;
  z-index: 2;
  text-align: center;
  color: #eef1ff;
  padding: 0 24px;
  max-width: 500px;
  pointer-events: none;
}

.dg-title {
  font-size: 44px;
  font-weight: 800;
  letter-spacing: 0.02em;
  background: linear-gradient(90deg, #a5b4fc, #818cf8, #6366f1);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.dg-sub {
  margin-top: 14px;
  font-size: 14px;
  line-height: 1.85;
  color: rgba(238, 241, 255, 0.78);
}
JavaScript
// マウス/タッチ位置を CSS変数に渡し、ドット格子のスポットライトを動かす
(() => {
  const stage = document.getElementById("dgStage");
  if (!stage) return; // null安全

  // 座標を stage 内の相対pxに変換して反映
  const move = (clientX, clientY) => {
    const r = stage.getBoundingClientRect();
    const x = clientX - r.left;
    const y = clientY - r.top;
    stage.style.setProperty("--mx", x + "px");
    stage.style.setProperty("--my", y + "px");
  };

  stage.addEventListener("pointermove", (e) => move(e.clientX, e.clientY), { passive: true });

  // 離れたら中央へ戻す
  stage.addEventListener("pointerleave", () => {
    const r = stage.getBoundingClientRect();
    stage.style.setProperty("--mx", r.width / 2 + "px");
    stage.style.setProperty("--my", r.height / 2 + "px");
  });

  // 初期位置を中央に
  requestAnimationFrame(() => {
    const r = stage.getBoundingClientRect();
    stage.style.setProperty("--mx", r.width / 2 + "px");
    stage.style.setProperty("--my", r.height / 2 + "px");
  });
})();

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

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

# 追加してほしい効果
ドット/グリッド背景(背景 & グラデーション)
CSSのドット格子にマウス追従のスポットライトを重ねた背景。マスクで照らした部分だけドットを濃く見せます。ダッシュボード向け。

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

# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- ドット/グリッド背景: CSSのドット格子にスポットライトを追従させる -->
<div class="dg-stage" id="dgStage">
  <div class="dg-dots"></div>
  <div class="dg-glow" id="dgGlow"></div>
  <div class="dg-content">
    <h1 class="dg-title">Dot Grid</h1>
    <p class="dg-sub">マウスに追従するスポットライトでドット格子を照らす、ダッシュボード向けの背景です。</p>
  </div>
</div>

【CSS】
/* ドット格子 + マウス追従グロー */
* { box-sizing: border-box; margin: 0; padding: 0; }

.dg-stage {
  position: relative;
  min-height: 360px;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: #0b0e16;
  font-family: "Segoe UI", "Hiragino Sans", system-ui, sans-serif;
  --mx: 50%;
  --my: 50%;
}

/* ドット格子: 繰り返し radial-gradient で点を打つ */
.dg-dots {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(120, 150, 255, 0.35) 1.4px, transparent 1.5px);
  background-size: 26px 26px;
  /* マウス周辺だけドットを濃く見せるマスク */
  -webkit-mask-image: radial-gradient(240px 240px at var(--mx) var(--my), #000 0%, rgba(0,0,0,0.25) 60%, transparent 100%);
  mask-image: radial-gradient(240px 240px at var(--mx) var(--my), #000 0%, rgba(0,0,0,0.25) 60%, transparent 100%);
}

/* マウス位置に淡い光 */
.dg-glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(300px 300px at var(--mx) var(--my), rgba(99, 102, 241, 0.22), transparent 70%);
  pointer-events: none;
  transition: background 0.08s linear;
}

.dg-content {
  position: relative;
  z-index: 2;
  text-align: center;
  color: #eef1ff;
  padding: 0 24px;
  max-width: 500px;
  pointer-events: none;
}

.dg-title {
  font-size: 44px;
  font-weight: 800;
  letter-spacing: 0.02em;
  background: linear-gradient(90deg, #a5b4fc, #818cf8, #6366f1);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.dg-sub {
  margin-top: 14px;
  font-size: 14px;
  line-height: 1.85;
  color: rgba(238, 241, 255, 0.78);
}

【JavaScript】
// マウス/タッチ位置を CSS変数に渡し、ドット格子のスポットライトを動かす
(() => {
  const stage = document.getElementById("dgStage");
  if (!stage) return; // null安全

  // 座標を stage 内の相対pxに変換して反映
  const move = (clientX, clientY) => {
    const r = stage.getBoundingClientRect();
    const x = clientX - r.left;
    const y = clientY - r.top;
    stage.style.setProperty("--mx", x + "px");
    stage.style.setProperty("--my", y + "px");
  };

  stage.addEventListener("pointermove", (e) => move(e.clientX, e.clientY), { passive: true });

  // 離れたら中央へ戻す
  stage.addEventListener("pointerleave", () => {
    const r = stage.getBoundingClientRect();
    stage.style.setProperty("--mx", r.width / 2 + "px");
    stage.style.setProperty("--my", r.height / 2 + "px");
  });

  // 初期位置を中央に
  requestAnimationFrame(() => {
    const r = stage.getBoundingClientRect();
    stage.style.setProperty("--mx", r.width / 2 + "px");
    stage.style.setProperty("--my", r.height / 2 + "px");
  });
})();

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

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