ガラスカード(backdrop-filter)

backdrop-filter で背景をぼかした半透明のガラスカード。マウスに追従する光沢で、料金プランや特集カードの主役に使えます。

#css#glassmorphism#backdrop-filter#javascript

ライブデモ

使用例(お題: アイドルグループ Sakura)

この技法を「アイドルグループ Sakura」というテーマのダミーサイトで実際に使った例です。

HTML
<!-- 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>
CSS
/* 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; }
}
JavaScript
// ガラスカード上のマウス位置を 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 ハイライトの不透明度を調整するなどで質感を作り分けられます。

コード

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);
  });
}

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

このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私の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で提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。