ブレンドモードカーソル
mix-blend-mode:difference でカーソル下の色を反転させる円。カラフルな作品集やポートフォリオの印象的なアクセントになります。
ライブデモ
使用例(お題: アイドルグループ Sakura)
この技法を「アイドルグループ Sakura」というテーマのダミーサイトで実際に使った例です。
HTML
<!-- Sakura: 楽曲MVギャラリー1画面。差分ブレンドの反転カーソルを主役に -->
<div class="sk" data-blend-root>
<header class="sk__bar">
<span class="sk__logo">🌸 Sakura</span>
<span class="sk__sub">MUSIC VIDEO</span>
</header>
<section class="sk__gallery">
<h1 class="sk__title">最新MV「桜色サイダー」</h1>
<div class="sk__grid">
<div class="sk__cell sk__cell--a"><span>桜色サイダー</span></div>
<div class="sk__cell sk__cell--b"><span>ナイトブルーム</span></div>
<div class="sk__cell sk__cell--c"><span>はなびら Letter</span></div>
<div class="sk__cell sk__cell--d"><span>春陽メロディ</span></div>
</div>
<p class="sk__hint">カーソルを重ねると色が反転します</p>
</section>
<!-- 主役: 差分ブレンドの反転円 -->
<div class="blend-cursor" data-blend></div>
</div>
CSS
/* Sakura MVギャラリー: 桜ピンク + カラフルなセル(差分反転が映える) */
* { box-sizing: border-box; }
body {
margin: 0;
font-family: "Hiragino Sans", "Yu Gothic", system-ui, sans-serif;
color: #3a2b30;
overflow: hidden;
}
.sk {
position: relative;
height: 400px;
background: linear-gradient(160deg, #fff 0%, #fdf4f7 100%);
cursor: none;
overflow: hidden;
}
/* ヘッダー */
.sk__bar {
display: flex;
align-items: baseline;
gap: 14px;
padding: 14px 26px;
}
.sk__logo {
font-weight: 800;
font-size: 17px;
letter-spacing: .06em;
color: #e06a92;
}
.sk__sub {
font-size: 11px;
font-weight: 700;
letter-spacing: .24em;
color: #b39aa2;
}
/* ギャラリー */
.sk__gallery {
padding: 0 26px 18px;
}
.sk__title {
margin: 0 0 12px;
font-size: 18px;
font-weight: 800;
}
.sk__grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
}
.sk__cell {
height: 210px;
border-radius: 14px;
display: flex;
align-items: flex-end;
padding: 12px;
color: #fff;
font-weight: 700;
font-size: 13px;
text-shadow: 0 1px 6px rgba(0,0,0,.3);
}
/* 反転が映えるカラフルなカバー */
.sk__cell--a { background: linear-gradient(150deg, #ff9bbb, #e0489a); }
.sk__cell--b { background: linear-gradient(150deg, #6a8bff, #3b2b7a); }
.sk__cell--c { background: linear-gradient(150deg, #ffd166, #ff7b54); }
.sk__cell--d { background: linear-gradient(150deg, #7be0c2, #2e9e8a); }
.sk__hint {
margin: 12px 0 0;
font-size: 11px;
letter-spacing: .04em;
color: #b39aa2;
}
/* 主役: 差分ブレンドの反転円 */
.blend-cursor {
position: fixed;
top: 0;
left: 0;
width: 64px;
height: 64px;
margin: -32px 0 0 -32px;
border-radius: 50%;
background: #fff;
mix-blend-mode: difference; /* 下の色を反転 */
pointer-events: none;
z-index: 50;
opacity: 0;
transition: opacity .3s ease, width .25s ease, height .25s ease, margin .25s ease;
}
.sk.is-active .blend-cursor { opacity: 1; }
.blend-cursor.is-big {
width: 110px;
height: 110px;
margin: -55px 0 0 -55px;
}
JavaScript
// Sakura: 差分ブレンドの反転カーソル。待機中はグリッド上を自動で巡回、操作で本物に追従
(() => {
const root = document.querySelector('[data-blend-root]');
const blend = document.querySelector('[data-blend]');
if (!root || !blend) return; // null安全
let px = 0, py = 0;
let usePointer = false;
let lastMove = 0;
const IDLE = 1500;
root.classList.add('is-active');
root.addEventListener('pointermove', (e) => {
usePointer = true;
lastMove = performance.now();
px = e.clientX; py = e.clientY;
});
// 押下中は拡大して反転範囲を強調
root.addEventListener('pointerdown', () => blend.classList.add('is-big'));
root.addEventListener('pointerup', () => blend.classList.remove('is-big'));
root.addEventListener('pointerleave', () => {
blend.classList.remove('is-big');
usePointer = false;
});
// 仮想カーソルの自動経路: カラフルなセル帯を左右に横切る
const autoPos = (t) => {
const r = root.getBoundingClientRect();
const cx = r.left + r.width / 2;
const cy = r.top + r.height * 0.62; // セル帯の高さ付近
return {
x: cx + Math.sin(t * 0.0008) * r.width * 0.38,
y: cy + Math.sin(t * 0.0013 + 0.6) * r.height * 0.1,
};
};
const loop = (now) => {
if (usePointer && now - lastMove > IDLE) usePointer = false;
if (!usePointer) {
const p = autoPos(now);
px = p.x; py = p.y;
// 自動時は一定周期で“ふくらむ”脈動を加える
const big = Math.sin(now * 0.0025) > 0.6;
blend.classList.toggle('is-big', big);
}
blend.style.transform = `translate(${px}px, ${py}px)`;
requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
})();
コード
HTML
<!-- ブレンドモードカーソル:mix-blend-mode:difference で背景色を反転する円 -->
<div class="stage" data-blend-root>
<div class="bands">
<span class="band b1"></span>
<span class="band b2"></span>
<span class="band b3"></span>
<span class="band b4"></span>
</div>
<div class="content">
<h1 class="title">BLEND MODE</h1>
<p class="lead">カーソルが触れた色を反転させる difference ブレンド。</p>
</div>
<!-- ブレンドする円 -->
<div class="blend-cursor" data-blend></div>
</div>
CSS
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
.stage {
position: relative;
height: 360px;
overflow: hidden;
display: grid;
place-items: center;
background: #f4f1ea;
font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
cursor: none;
}
/* 背景に色帯を敷いてブレンドの効果を見せる */
.bands { position: absolute; inset: 0; display: flex; }
.band { flex: 1; height: 100%; }
.b1 { background: #ff5d73; }
.b2 { background: #ffd23f; }
.b3 { background: #1b9aaa; }
.b4 { background: #3d348b; }
.content {
position: relative;
z-index: 1;
text-align: center;
padding: 24px;
pointer-events: none;
/* 文字も difference で白く反転させ視認性を確保 */
color: #fff;
mix-blend-mode: difference;
}
.title {
margin: 0 0 10px;
font-size: clamp(34px, 8vw, 64px);
font-weight: 900;
letter-spacing: .08em;
}
.lead { margin: 0; font-size: 14px; font-weight: 600; }
/* ブレンドカーソル本体 */
.blend-cursor {
position: fixed;
top: 0; left: 0;
width: 70px; height: 70px;
border-radius: 50%;
background: #fff;
mix-blend-mode: difference; /* 下の色を反転 */
transform: translate(-50%, -50%);
pointer-events: none;
z-index: 9999;
opacity: 0; /* 初回移動まで非表示(隅の反転アーティファクトを防ぐ) */
transition: width .25s ease, height .25s ease, opacity .3s ease;
will-change: transform;
}
[data-blend-root].is-active .blend-cursor { opacity: 1; }
.blend-cursor.is-big { width: 130px; height: 130px; }
JavaScript
// ブレンドモードカーソル:円を追従させ、押下中は拡大
(() => {
const root = document.querySelector('[data-blend-root]');
const blend = document.querySelector('[data-blend]');
if (!root || !blend) return; // null安全
// 円を即時追従(transformのみ更新でGPU合成)
root.addEventListener('pointermove', (e) => {
blend.style.transform = `translate(${e.clientX}px, ${e.clientY}px) translate(-50%, -50%)`;
if (!root.classList.contains('is-active')) root.classList.add('is-active');
});
// 押している間は拡大して反転範囲を強調
root.addEventListener('pointerdown', () => blend.classList.add('is-big'));
root.addEventListener('pointerup', () => blend.classList.remove('is-big'));
root.addEventListener('pointerleave', () => {
blend.classList.remove('is-big');
root.classList.remove('is-active');
});
})();
🤖 AIエージェント用プロンプト
このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「ブレンドモードカーソル」の効果を追加してください。
# 追加してほしい効果
ブレンドモードカーソル(カスタムカーソル)
mix-blend-mode:difference でカーソル下の色を反転させる円。カラフルな作品集やポートフォリオの印象的なアクセントになります。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- ブレンドモードカーソル:mix-blend-mode:difference で背景色を反転する円 -->
<div class="stage" data-blend-root>
<div class="bands">
<span class="band b1"></span>
<span class="band b2"></span>
<span class="band b3"></span>
<span class="band b4"></span>
</div>
<div class="content">
<h1 class="title">BLEND MODE</h1>
<p class="lead">カーソルが触れた色を反転させる difference ブレンド。</p>
</div>
<!-- ブレンドする円 -->
<div class="blend-cursor" data-blend></div>
</div>
【CSS】
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
.stage {
position: relative;
height: 360px;
overflow: hidden;
display: grid;
place-items: center;
background: #f4f1ea;
font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
cursor: none;
}
/* 背景に色帯を敷いてブレンドの効果を見せる */
.bands { position: absolute; inset: 0; display: flex; }
.band { flex: 1; height: 100%; }
.b1 { background: #ff5d73; }
.b2 { background: #ffd23f; }
.b3 { background: #1b9aaa; }
.b4 { background: #3d348b; }
.content {
position: relative;
z-index: 1;
text-align: center;
padding: 24px;
pointer-events: none;
/* 文字も difference で白く反転させ視認性を確保 */
color: #fff;
mix-blend-mode: difference;
}
.title {
margin: 0 0 10px;
font-size: clamp(34px, 8vw, 64px);
font-weight: 900;
letter-spacing: .08em;
}
.lead { margin: 0; font-size: 14px; font-weight: 600; }
/* ブレンドカーソル本体 */
.blend-cursor {
position: fixed;
top: 0; left: 0;
width: 70px; height: 70px;
border-radius: 50%;
background: #fff;
mix-blend-mode: difference; /* 下の色を反転 */
transform: translate(-50%, -50%);
pointer-events: none;
z-index: 9999;
opacity: 0; /* 初回移動まで非表示(隅の反転アーティファクトを防ぐ) */
transition: width .25s ease, height .25s ease, opacity .3s ease;
will-change: transform;
}
[data-blend-root].is-active .blend-cursor { opacity: 1; }
.blend-cursor.is-big { width: 130px; height: 130px; }
【JavaScript】
// ブレンドモードカーソル:円を追従させ、押下中は拡大
(() => {
const root = document.querySelector('[data-blend-root]');
const blend = document.querySelector('[data-blend]');
if (!root || !blend) return; // null安全
// 円を即時追従(transformのみ更新でGPU合成)
root.addEventListener('pointermove', (e) => {
blend.style.transform = `translate(${e.clientX}px, ${e.clientY}px) translate(-50%, -50%)`;
if (!root.classList.contains('is-active')) root.classList.add('is-active');
});
// 押している間は拡大して反転範囲を強調
root.addEventListener('pointerdown', () => blend.classList.add('is-big'));
root.addEventListener('pointerup', () => blend.classList.remove('is-big'));
root.addEventListener('pointerleave', () => {
blend.classList.remove('is-big');
root.classList.remove('is-active');
});
})();
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。