ドット/グリッド背景
CSSのドット格子にマウス追従のスポットライトを重ねた背景。マスクで照らした部分だけドットを濃く見せます。ダッシュボード向け。
ライブデモ
使用例(お題: 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で提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。