ガラスカード(backdrop-filter)
backdrop-filter で背景をぼかした半透明のガラスカード。マウスに追従する光沢で、料金プランや特集カードの主役に使えます。
ライブデモ
使用例(お題: アイドルグループ Sakura)
この技法を「アイドルグループ Sakura」というテーマのダミーサイトで実際に使った例です。
<!-- Sakura メンバープロフィール:写真の上にフロストガラスカード -->
<section class="sk-profile">
<!-- 背景のメンバー写真(picsum) -->
<div class="sk-profile__photo" aria-hidden="true"></div>
<span class="sk-petal sk-petal--1"></span>
<span class="sk-petal sk-petal--2"></span>
<span class="sk-petal sk-petal--3"></span>
<!-- 写真の上に重なるガラスプロフィールカード -->
<article class="sk-card" id="skCard">
<div class="sk-card__shine"></div>
<span class="sk-card__badge">MEMBER 03</span>
<p class="sk-card__color">桜ピンク担当</p>
<h2 class="sk-card__name">桜井 ひな<small>Hina Sakurai</small></h2>
<p class="sk-card__text">透明感のある歌声とふんわり笑顔が魅力。趣味はお菓子作りと写真撮影です。</p>
<div class="sk-card__stats">
<div><b>5/12</b><span>誕生日</span></div>
<div><b>O型</b><span>血液型</span></div>
<div><b>大阪</b><span>出身</span></div>
</div>
<button class="sk-card__btn" type="button">プロフィールを見る</button>
</article>
</section>
/* Sakura:桜ピンクのメンバープロフィール */
:root {
--pink: #ffd1e0;
--pink-deep: #ff8fb3;
--white: #ffffff;
--gray: #fbf7f9;
}
* { box-sizing: border-box; }
body {
margin: 0;
height: 400px;
display: grid;
place-items: center;
font-family: "Hiragino Kaku Gothic ProN", "Segoe UI", system-ui, sans-serif;
background: var(--gray);
overflow: hidden;
}
/* 写真エリア(カードの土台になる) */
.sk-profile {
position: relative;
width: 100%;
height: 400px;
display: grid;
place-items: center;
background: linear-gradient(160deg, #ffe3ee 0%, #ffd1e0 60%, #ffc0d8 100%);
overflow: hidden;
}
/* 背景のメンバー写真:薄く桜色に染める */
.sk-profile__photo {
position: absolute;
inset: 0;
background: url("https://picsum.photos/600/500?random=31") center/cover no-repeat;
filter: saturate(1.05);
}
.sk-profile__photo::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(255,143,179,0.5), rgba(255,209,224,0.35));
mix-blend-mode: soft-light;
}
/* 舞う花びら */
.sk-petal {
position: absolute;
width: 16px; height: 16px;
background: rgba(255,255,255,0.85);
border-radius: 0 100% 0 100%;
filter: blur(0.3px);
animation: skFall 9s linear infinite;
pointer-events: none;
}
.sk-petal--1 { left: 14%; top: -20px; animation-delay: 0s; }
.sk-petal--2 { left: 62%; top: -20px; animation-delay: -3s; background: rgba(255,209,224,0.9); }
.sk-petal--3 { left: 84%; top: -20px; animation-delay: -6s; }
@keyframes skFall {
0% { transform: translateY(-20px) rotate(0deg); opacity: 0; }
10% { opacity: 0.9; }
100% { transform: translateY(440px) rotate(320deg); opacity: 0; }
}
/* ガラスプロフィールカード:写真の上にフロスト */
.sk-card {
position: relative;
width: min(300px, 82vw);
padding: 22px 24px 24px;
border-radius: 24px;
background: rgba(255, 255, 255, 0.34);
border: 1px solid rgba(255, 255, 255, 0.6);
-webkit-backdrop-filter: blur(14px) saturate(1.3);
backdrop-filter: blur(14px) saturate(1.3);
box-shadow: 0 12px 36px rgba(214, 94, 140, 0.28), inset 0 1px 0 rgba(255,255,255,0.7);
color: #6a2740;
overflow: hidden;
transition: transform 0.25s ease;
}
.sk-card:hover { transform: translateY(-4px); }
/* マウス追従の光沢 */
.sk-card__shine {
position: absolute;
inset: 0;
background: radial-gradient(200px circle at var(--mx, 50%) var(--my, 0%),
rgba(255, 255, 255, 0.7), transparent 60%);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
}
.sk-card:hover .sk-card__shine { opacity: 1; }
.sk-card__badge {
display: inline-block;
font-size: 10px;
letter-spacing: 0.22em;
padding: 4px 11px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.55);
border: 1px solid rgba(255, 255, 255, 0.7);
color: #c94d7d;
font-weight: 700;
}
.sk-card__color { margin: 12px 0 2px; font-size: 12px; color: #d65e8c; font-weight: 600; }
.sk-card__name {
margin: 0 0 8px;
font-size: 24px;
font-weight: 800;
letter-spacing: 0.02em;
display: flex;
align-items: baseline;
gap: 8px;
}
.sk-card__name small { font-size: 11px; font-weight: 500; color: #b07089; letter-spacing: 0.08em; }
.sk-card__text { margin: 0 0 14px; font-size: 12.5px; line-height: 1.7; color: #7a3553; }
.sk-card__stats {
display: flex;
gap: 6px;
margin-bottom: 16px;
}
.sk-card__stats > div {
flex: 1;
text-align: center;
padding: 8px 4px;
border-radius: 12px;
background: rgba(255, 255, 255, 0.4);
}
.sk-card__stats b { display: block; font-size: 15px; color: #c94d7d; }
.sk-card__stats span { font-size: 10px; color: #9a6076; }
.sk-card__btn {
font: inherit;
font-size: 13px;
font-weight: 700;
color: #fff;
background: linear-gradient(135deg, #ff9cc0, #ff7aa8);
border: none;
padding: 11px 0;
width: 100%;
border-radius: 999px;
cursor: pointer;
box-shadow: 0 6px 16px rgba(255, 122, 168, 0.45);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.sk-card__btn:hover { transform: scale(1.03); box-shadow: 0 8px 20px rgba(255, 122, 168, 0.55); }
.sk-card__btn:active { transform: scale(0.98); }
@media (prefers-reduced-motion: reduce) {
.sk-petal { animation: none; opacity: 0; }
.sk-card, .sk-card__btn { transition: none; }
}
// ガラスカード上のマウス位置を CSS変数へ反映し、光沢を追従させる
const card = document.getElementById("skCard");
if (card) {
card.addEventListener("pointermove", (e) => {
const rect = card.getBoundingClientRect();
// カード内の相対位置(%)を算出
const mx = ((e.clientX - rect.left) / rect.width) * 100;
const my = ((e.clientY - rect.top) / rect.height) * 100;
card.style.setProperty("--mx", `${mx}%`);
card.style.setProperty("--my", `${my}%`);
});
// 離れたら光沢を上端へ戻す
card.addEventListener("pointerleave", () => {
card.style.setProperty("--mx", "50%");
card.style.setProperty("--my", "0%");
});
// ボタンで軽いフィードバック(ファン向けの一言)
const btn = card.querySelector(".sk-card__btn");
btn?.addEventListener("click", () => {
const label = btn.textContent;
btn.textContent = "ありがとう♪";
setTimeout(() => { btn.textContent = label; }, 1400);
});
}
実装ガイド
使いどころ
料金プランや特集カード、ヒーロー上に重ねる訴求カードなど、カラフルな背景の上で主役を張らせたいUIに効果的です。マウス追従の光沢が加わるため、CTAを含む単体の注目カードに向きます。
実装時の注意点
効果の核は背景を透過させる background: rgba(...) と backdrop-filter: blur() で、必ず両方が揃って初めてガラスに見えます。inset 0 1px 0 rgba(255,255,255,.4) のような上端ハイライトと薄い白縁で立体感を補強し、文字は白+やや高い不透明度でコントラストを確保します。光沢は radial-gradient の中心位置を CSS 変数(--mx/--my)で更新するだけなので、JS は座標計算のみで軽量です。
対応ブラウザ
backdrop-filter は Chrome/Edge は標準対応、Firefox は 103 以降で標準対応、Safari は古くから -webkit-backdrop-filter プレフィックス付きが必要です(本デモも -webkit- と無印を併記済み)。未対応環境では blur が無視され半透明背景だけになるため、background の rgba を単独でも読める濃さにしておくとフォールバックとして機能します。
よくある失敗
背景が無地・単色だと透過しても変化が見えず、ガラス効果が成立しません。白文字を半透明の明るい背景に重ねるとコントラストが落ちて WCAG 1.4.3(4.5:1)を割りがちで、blur を強くするほど背後の輪郭が消えて視認性も上がる一方、要素を画面に多数置くと backdrop-filter の再描画が GPU 負荷になりスクロールがカクつきます。
応用例
背景に animation で漂う blur 済みカラーブロブ(blob)を置くと透過の妙が際立ちます。--blur をメディアクエリやJSで可変にしてモバイルでは弱める、saturate() を足して彩度を上げる、ダーク背景では border と inset ハイライトの不透明度を調整するなどで質感を作り分けられます。
コード
<!-- 背景の彩りブロブ(ガラスの透過を引き立てる) -->
<div class="scene">
<span class="blob blob--1"></span>
<span class="blob blob--2"></span>
<span class="blob blob--3"></span>
<!-- ガラスカード本体 -->
<article class="glass-card" id="glassCard">
<div class="glass-card__shine"></div>
<span class="glass-card__badge">PREMIUM</span>
<h2 class="glass-card__title">Frosted Glass</h2>
<p class="glass-card__text">backdrop-filter で背景をぼかした半透明カード。マウスを乗せると光沢が追従します。</p>
<button class="glass-card__btn" type="button">詳しく見る</button>
</article>
</div>
/* カスタムプロパティで色とぼかし量を一元管理 */
:root {
--glass-bg: rgba(255, 255, 255, 0.14);
--glass-border: rgba(255, 255, 255, 0.35);
--blur: 16px;
}
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 360px;
display: grid;
place-items: center;
font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
/* 深みのある斜めグラデ背景 */
background: linear-gradient(135deg, #1e3a8a 0%, #5b21b6 50%, #be185d 100%);
overflow: hidden;
}
/* 背景に漂う色ブロブ(ぼかしの効果を強調) */
.scene { position: relative; width: 100%; height: 360px; display: grid; place-items: center; }
.blob {
position: absolute;
border-radius: 50%;
filter: blur(30px);
opacity: 0.85;
animation: float 9s ease-in-out infinite;
}
.blob--1 { width: 180px; height: 180px; background: #38bdf8; top: 12%; left: 16%; }
.blob--2 { width: 150px; height: 150px; background: #f472b6; bottom: 10%; right: 18%; animation-delay: -3s; }
.blob--3 { width: 120px; height: 120px; background: #fbbf24; top: 40%; right: 38%; animation-delay: -6s; }
@keyframes float {
0%, 100% { transform: translateY(0) scale(1); }
50% { transform: translateY(-22px) scale(1.08); }
}
/* ガラスカード:半透明+ぼかし+繊細な縁取り */
.glass-card {
position: relative;
width: min(320px, 80vw);
padding: 28px 26px 30px;
border-radius: 22px;
background: var(--glass-bg);
border: 1px solid var(--glass-border);
-webkit-backdrop-filter: blur(var(--blur));
backdrop-filter: blur(var(--blur));
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.4);
color: #fff;
overflow: hidden;
transition: transform 0.25s ease;
}
.glass-card:hover { transform: translateY(-4px); }
/* マウス位置に追従する光沢(JSで --mx/--my を更新) */
.glass-card__shine {
position: absolute;
inset: 0;
background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 0%),
rgba(255, 255, 255, 0.45), transparent 60%);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
}
.glass-card:hover .glass-card__shine { opacity: 1; }
.glass-card__badge {
display: inline-block;
font-size: 11px;
letter-spacing: 0.18em;
padding: 4px 10px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.22);
border: 1px solid rgba(255, 255, 255, 0.3);
}
.glass-card__title { margin: 14px 0 8px; font-size: 26px; font-weight: 700; }
.glass-card__text { margin: 0 0 20px; font-size: 13.5px; line-height: 1.7; color: rgba(255, 255, 255, 0.88); }
.glass-card__btn {
font: inherit;
font-size: 13px;
color: #1e293b;
background: rgba(255, 255, 255, 0.92);
border: none;
padding: 10px 22px;
border-radius: 999px;
cursor: pointer;
font-weight: 600;
transition: background 0.2s ease, transform 0.2s ease;
}
.glass-card__btn:hover { background: #fff; transform: scale(1.04); }
.glass-card__btn:active { transform: scale(0.98); }
/* アニメ抑制設定への配慮 */
@media (prefers-reduced-motion: reduce) {
.blob { animation: none; }
.glass-card, .glass-card__btn { transition: none; }
}
// ガラスカード上のマウス位置を CSS変数へ反映し、光沢を追従させる
const card = document.getElementById("glassCard");
if (card) {
card.addEventListener("pointermove", (e) => {
const rect = card.getBoundingClientRect();
// カード内の相対位置(%)を算出
const mx = ((e.clientX - rect.left) / rect.width) * 100;
const my = ((e.clientY - rect.top) / rect.height) * 100;
card.style.setProperty("--mx", `${mx}%`);
card.style.setProperty("--my", `${my}%`);
});
// 離れたら光沢を上端中央に戻す(次回ホバー時の見え方を安定させる)
card.addEventListener("pointerleave", () => {
card.style.setProperty("--mx", "50%");
card.style.setProperty("--my", "0%");
});
// ボタンクリックで軽いフィードバック(コンソールエラーを出さない範囲で)
const btn = card.querySelector(".glass-card__btn");
btn?.addEventListener("click", () => {
btn.textContent = "ありがとう!";
setTimeout(() => { btn.textContent = "詳しく見る"; }, 1400);
});
}
🤖 AIエージェント用プロンプト
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「ガラスカード(backdrop-filter)」の効果を追加してください。
# 追加してほしい効果
ガラスカード(backdrop-filter)(グラス / ニューモーフィズム)
backdrop-filter で背景をぼかした半透明のガラスカード。マウスに追従する光沢で、料金プランや特集カードの主役に使えます。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- 背景の彩りブロブ(ガラスの透過を引き立てる) -->
<div class="scene">
<span class="blob blob--1"></span>
<span class="blob blob--2"></span>
<span class="blob blob--3"></span>
<!-- ガラスカード本体 -->
<article class="glass-card" id="glassCard">
<div class="glass-card__shine"></div>
<span class="glass-card__badge">PREMIUM</span>
<h2 class="glass-card__title">Frosted Glass</h2>
<p class="glass-card__text">backdrop-filter で背景をぼかした半透明カード。マウスを乗せると光沢が追従します。</p>
<button class="glass-card__btn" type="button">詳しく見る</button>
</article>
</div>
【CSS】
/* カスタムプロパティで色とぼかし量を一元管理 */
:root {
--glass-bg: rgba(255, 255, 255, 0.14);
--glass-border: rgba(255, 255, 255, 0.35);
--blur: 16px;
}
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 360px;
display: grid;
place-items: center;
font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
/* 深みのある斜めグラデ背景 */
background: linear-gradient(135deg, #1e3a8a 0%, #5b21b6 50%, #be185d 100%);
overflow: hidden;
}
/* 背景に漂う色ブロブ(ぼかしの効果を強調) */
.scene { position: relative; width: 100%; height: 360px; display: grid; place-items: center; }
.blob {
position: absolute;
border-radius: 50%;
filter: blur(30px);
opacity: 0.85;
animation: float 9s ease-in-out infinite;
}
.blob--1 { width: 180px; height: 180px; background: #38bdf8; top: 12%; left: 16%; }
.blob--2 { width: 150px; height: 150px; background: #f472b6; bottom: 10%; right: 18%; animation-delay: -3s; }
.blob--3 { width: 120px; height: 120px; background: #fbbf24; top: 40%; right: 38%; animation-delay: -6s; }
@keyframes float {
0%, 100% { transform: translateY(0) scale(1); }
50% { transform: translateY(-22px) scale(1.08); }
}
/* ガラスカード:半透明+ぼかし+繊細な縁取り */
.glass-card {
position: relative;
width: min(320px, 80vw);
padding: 28px 26px 30px;
border-radius: 22px;
background: var(--glass-bg);
border: 1px solid var(--glass-border);
-webkit-backdrop-filter: blur(var(--blur));
backdrop-filter: blur(var(--blur));
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.4);
color: #fff;
overflow: hidden;
transition: transform 0.25s ease;
}
.glass-card:hover { transform: translateY(-4px); }
/* マウス位置に追従する光沢(JSで --mx/--my を更新) */
.glass-card__shine {
position: absolute;
inset: 0;
background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 0%),
rgba(255, 255, 255, 0.45), transparent 60%);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
}
.glass-card:hover .glass-card__shine { opacity: 1; }
.glass-card__badge {
display: inline-block;
font-size: 11px;
letter-spacing: 0.18em;
padding: 4px 10px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.22);
border: 1px solid rgba(255, 255, 255, 0.3);
}
.glass-card__title { margin: 14px 0 8px; font-size: 26px; font-weight: 700; }
.glass-card__text { margin: 0 0 20px; font-size: 13.5px; line-height: 1.7; color: rgba(255, 255, 255, 0.88); }
.glass-card__btn {
font: inherit;
font-size: 13px;
color: #1e293b;
background: rgba(255, 255, 255, 0.92);
border: none;
padding: 10px 22px;
border-radius: 999px;
cursor: pointer;
font-weight: 600;
transition: background 0.2s ease, transform 0.2s ease;
}
.glass-card__btn:hover { background: #fff; transform: scale(1.04); }
.glass-card__btn:active { transform: scale(0.98); }
/* アニメ抑制設定への配慮 */
@media (prefers-reduced-motion: reduce) {
.blob { animation: none; }
.glass-card, .glass-card__btn { transition: none; }
}
【JavaScript】
// ガラスカード上のマウス位置を CSS変数へ反映し、光沢を追従させる
const card = document.getElementById("glassCard");
if (card) {
card.addEventListener("pointermove", (e) => {
const rect = card.getBoundingClientRect();
// カード内の相対位置(%)を算出
const mx = ((e.clientX - rect.left) / rect.width) * 100;
const my = ((e.clientY - rect.top) / rect.height) * 100;
card.style.setProperty("--mx", `${mx}%`);
card.style.setProperty("--my", `${my}%`);
});
// 離れたら光沢を上端中央に戻す(次回ホバー時の見え方を安定させる)
card.addEventListener("pointerleave", () => {
card.style.setProperty("--mx", "50%");
card.style.setProperty("--my", "0%");
});
// ボタンクリックで軽いフィードバック(コンソールエラーを出さない範囲で)
const btn = card.querySelector(".glass-card__btn");
btn?.addEventListener("click", () => {
btn.textContent = "ありがとう!";
setTimeout(() => { btn.textContent = "詳しく見る"; }, 1400);
});
}
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。