Prompt Share

フォーマット: SKILL生成メディア: テキスト

Apple風ガラスUI(Liquid Glass)デザイン実装スキル

カテゴリ: 開発・プログラミング 投稿者: こうた777 投稿日: 2026/07/26 04:37 使用AI: Claude Opus 5

SKILL定義 (Markdown)


name: liquid-glass-ui
description: Apple の Liquid Glass に着想を得た「すりガラス質感」のUIをWeb標準技術で実装するためのスキル。ナビゲーションバー、カード、ボタン、ドック、モーダルなどに半透明・ぼかし・光沢のマテリアル表現を適用したいとき、または既存UIのガラス表現が「安っぽい/読みにくい/重い」ときに使う。CSS(backdrop-filter)を前提とし、React/Vue/Tailwind いずれの環境でも適用できる。

Apple風ガラスUI(Liquid Glass)デザイン

概要

Apple が iOS 26 / macOS 26 世代で導入した Liquid Glass は、「板状の半透明パネル」ではなく 背後のコンテンツを屈折・彩度強調しながら透かすレンズ状のマテリアル として設計されている。Web でこれを再現する際、backdrop-filter: blur() を掛けただけの実装は必ず「ただの曇りガラス」に見える。

本物らしさを決めるのは以下の4点であり、ぼかし量ではない。

  1. 彩度の持ち上げ(saturate)— 背後の色が生きたまま透ける
  2. エッジのハイライト(inset の1pxライン)— レンズの縁が光る
  3. 背後のコンテンツ— 透かす対象がない場所にガラスは成立しない
  4. 可読性のための地力(コントラスト確保)

Apple の意匠そのものを複製するのではなく、上記の物理的な振る舞いを Web 標準で再現する。


適用判断

使うべき場面

  • 写真・グラデーション・動画・地図など、情報量のある背景の上に重なるレイヤー(ナビバー、ドック、フローティングパネル、オーバーレイ)
  • スクロールでコンテンツが下を通過する固定ヘッダー/ツールバー
  • 「浮いている」ことを伝えたい一時的UI(モーダル、トースト、ポップオーバー)

使ってはいけない場面

  • 単色の白/薄グレー背景 → ガラスが透かすものがなく、単なる灰色の箱になる
  • 長文の本文、表、フォームの入力領域 → 可読性コストが利得を上回る
  • 画面の大半を覆う面積 → GPU コストが跳ね、かつ質感が安くなる
  • 情報密度の高い管理画面 → 境界が曖昧になり操作精度が落ちる

判断基準:そのパネルを取り除いたとき、背後に見せる価値のある絵があるか。 無いなら不透明なサーフェスを使う。


実装手順

Step 1. 背景を先に作る

ガラスより先に 透かす対象 を用意する。無地の背景しかない場合は、ぼかした大きめの色ブロブ(radial-gradient を2〜3枚重ねる)を敷く。これが Liquid Glass の見えを 8 割決める。

Step 2. ベースマテリアルを当てる

assets/liquid-glass.css.glass を適用する。構成要素は以下:

要素 役割 目安
backdrop-filter: blur() 背後の分離 16–32px(大きい面ほど大きく)
backdrop-filter: saturate() 背後の色を生かす 160–200%
半透明の地色 可読性の下支え light: 白 50–65% / dark: 濃色 40–55%
border: 1px レンズの外縁 白 45–60%(dark は 10–18%)
inset ハイライト 上端の光の入り 上 白60% / 下 白12%
外側シャドウ 浮遊感 大きくぼかして低不透明度

Step 3. スペキュラハイライトを重ねる

::before に斜め方向の白のグラデーションを敷く(左上 45% → 途中 8% → 0%)。これが無いと平坦な半透明板に見える。コンテンツは z-index: 1 で上に置くこと。

Step 4. 角丸と階層を整える

  • 角丸は大きめ(パネル 20–28px、ボタンは pill)
  • ガラスの入れ子は 1 段まで。 ガラスの上にガラスを重ねると、内側がぼかし済みの出力を再サンプリングして濁る
  • 兄弟要素として並べるのは可。親子で重ねない

Step 5. モーションを付ける

  • 押下:transform: scale(.96)、イージングは cubic-bezier(.32,.72,0,1)
  • ホバー:わずかな浮上(translateY -1px)+ シャドウ拡大
  • blur 値はアニメーションさせない(毎フレーム再合成が走り確実に落ちる)。動かすのは transformopacity のみ

Step 6. 可読性とフォールバックを検証する

必須。詳細は reference/checklist.md


可読性(最優先事項)

ガラスは背景次第でコントラストが変動するため、最悪ケースの背景で検証する

  • 本文テキストは 4.5:1、大きい文字・アイコンは 3:1 を、想定される最も明るい背景と最も暗い背景の両方で満たす
  • 満たせない場合は「ぼかしを強める」のではなく 地色の不透明度を上げる。ぼかしはコントラストを改善しない
  • テキストに text-shadow を足して誤魔化さない。滲んで安く見える
  • @media (prefers-reduced-transparency: reduce)(prefers-contrast: more) で不透明サーフェスに切り替える(実装済み)

パフォーマンス / 既知の落とし穴

  • backdrop-filter は GPU 合成コストが高い。同時に画面内へ置くのは 3–4 枚までを目安にする
  • 祖先要素に filter / backdrop-filter / 一部の transform があると、子の backdrop-filter が効かない・崩れる
  • backdrop-filter を持つ要素は新しいスタッキングコンテキストを作る。z-index の前提が変わる点に注意
  • Safari は -webkit-backdrop-filter の併記が必要
  • border-radius を効かせるには、はみ出す子要素側で overflow: hidden を検討する
  • 未対応環境向けに @supports not (backdrop-filter: blur(1px)) の分岐を必ず置く

アンチパターン

NG 直し方
全パーツをガラスにする ガラスは画面内 1–2 種類の役割に限定し、他は不透明にする
無地背景の上に置く 背景に色を作る、またはガラスをやめる
blur だけ強くする(60px+) blur を 20px 前後に戻し、saturate と地色不透明度で質感を出す
縁のハイライトが無い 1px border + inset ハイライトを入れる。これが最も効く
ガラスの多段ネスト 1 段に潰す
白文字を明るい背景のガラスに載せる 地色を濃色側に切り替えるか、文字色を反転する

完了条件

  • 明るい背景・暗い背景の両方でコントラスト基準を満たす
  • ライト/ダーク両モードで確認済み
  • prefers-reduced-transparency で不透明にフォールバックする
  • ガラスのネストが 1 段以下
  • 画面内の backdrop-filter 要素が 4 枚以下
  • blur 値をアニメーションしていない
  • Safari 接頭辞を併記済み

同梱リソース

  • assets/liquid-glass.css — トークンと .glass / バー / カード / ボタン / ドックの実装一式
  • reference/checklist.md — レビュー用チェックリストと調整早見表

追加リソース2ファイル

assets/liquid-glass.css参照資料 · css
/* ============================================================
   Liquid Glass UI — base material & components
   Apple の Liquid Glass に着想を得た Web 標準実装
   ============================================================ */

/* ---------- 1. Design tokens ---------- */
:root {
  --glass-blur: 24px;
  --glass-saturate: 180%;
  --glass-tint: 255 255 255;   /* 地色 RGB */
  --glass-alpha: 0.55;         /* 地色の不透明度 = 可読性のつまみ */
  --glass-radius: 22px;
  --glass-border: rgba(255, 255, 255, 0.55);
  --glass-hi-top: rgba(255, 255, 255, 0.60);
  --glass-hi-bottom: rgba(255, 255, 255, 0.12);
  --glass-shadow: 0 12px 40px rgba(0, 0, 0, 0.18);
  --glass-text: #10131a;
  --glass-ease: cubic-bezier(0.32, 0.72, 0, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --glass-tint: 22 24 28;
    --glass-alpha: 0.48;
    --glass-border: rgba(255, 255, 255, 0.14);
    --glass-hi-top: rgba(255, 255, 255, 0.22);
    --glass-hi-bottom: rgba(255, 255, 255, 0.05);
    --glass-shadow: 0 16px 48px rgba(0, 0, 0, 0.50);
    --glass-text: #f2f4f8;
  }
}

/* ---------- 2. 透かす背景を作る(必須) ---------- */
/* ガラスは背後に情報が無いと成立しない。無地ページには敷いておく。 */
.glass-backdrop {
  position: relative;
  min-height: 100%;
  background-color: #eef1f6;
  background-image:
    radial-gradient(60% 55% at 18% 22%, rgba(120, 170, 255, 0.85), transparent 70%),
    radial-gradient(55% 50% at 82% 30%, rgba(255, 140, 190, 0.70), transparent 70%),
    radial-gradient(70% 60% at 50% 92%, rgba(120, 235, 210, 0.65), transparent 72%);
}

@media (prefers-color-scheme: dark) {
  .glass-backdrop { background-color: #0b0d12; }
}

/* ---------- 3. ベースマテリアル ---------- */
.glass {
  position: relative;
  isolation: isolate;
  color: var(--glass-text);
  background: rgb(var(--glass-tint) / var(--glass-alpha));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border: 1px solid var(--glass-border);
  border-radius: var(--glass-radius);
  box-shadow:
    var(--glass-shadow),
    inset 0 1px 0 var(--glass-hi-top),
    inset 0 -1px 0 var(--glass-hi-bottom);
}

/* スペキュラハイライト:これが無いと平坦な半透明板に見える */
.glass::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(
    150deg,
    rgba(255, 255, 255, 0.45) 0%,
    rgba(255, 255, 255, 0.08) 34%,
    rgba(255, 255, 255, 0) 60%
  );
}

/* コンテンツはハイライトより上に置く */
.glass > * {
  position: relative;
  z-index: 1;
}

/* 背景が激しい場合の可読性補強(ぼかしではなく地色で稼ぐ) */
.glass--solidify { --glass-alpha: 0.78; }

/* ---------- 4. コンポーネント ---------- */

/* 固定ナビゲーションバー */
.glass-bar {
  --glass-blur: 30px;
  --glass-radius: 0px;
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 20px;
  border-inline: none;
  border-top: none;
}

/* フローティングカード / パネル */
.glass-card {
  padding: 20px 22px;
}

/* ボタン(pill) */
.glass-btn {
  --glass-radius: 999px;
  --glass-blur: 16px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 20px;
  font: inherit;
  font-weight: 590;
  cursor: pointer;
  transition:
    transform 0.28s var(--glass-ease),
    box-shadow 0.28s var(--glass-ease),
    background-color 0.28s var(--glass-ease);
}

.glass-btn:hover {
  transform: translateY(-1px);
  background: rgb(var(--glass-tint) / calc(var(--glass-alpha) + 0.12));
}

.glass-btn:active { transform: scale(0.96); }

.glass-btn:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* ドック / ツールバー */
.glass-dock {
  --glass-radius: 26px;
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  display: flex;
  gap: 6px;
  padding: 8px;
}

/* ドック内の項目はガラスを重ねない(ネスト禁止)。透明なチップにする。 */
.glass-dock__item {
  position: relative;
  z-index: 1;
  border: 0;
  border-radius: 18px;
  padding: 10px 14px;
  background: rgb(var(--glass-tint) / 0.28);
  color: inherit;
  cursor: pointer;
  transition: background-color 0.2s var(--glass-ease), transform 0.2s var(--glass-ease);
}

.glass-dock__item:hover { background: rgb(var(--glass-tint) / 0.5); }
.glass-dock__item:active { transform: scale(0.94); }

/* ---------- 5. フォールバック(必須) ---------- */

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background: rgb(var(--glass-tint) / 0.94); }
}

@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
  .glass {
    background: rgb(var(--glass-tint) / 0.97);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .glass::before { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .glass-btn,
  .glass-dock__item { transition: none; }
  .glass-btn:hover { transform: none; }
}
reference/checklist.md参照資料 · markdown
# Liquid Glass レビューチェックリスト

## A. 成立条件

- [ ] ガラスの背後に、透かす価値のある絵(写真・グラデーション・スクロールするコンテンツ)がある
- [ ] ガラスを使う役割が画面内で 1〜2 種類に絞られている
- [ ] 本文・表・入力欄など「読ませる/操作させる」領域はガラスの上に載っていない

## B. 質感

- [ ] `saturate()` が 160〜200% で入っている(blur だけになっていない)
- [ ] 1px の border と inset ハイライトで縁が光っている
- [ ] スペキュラハイライト(斜めの白グラデ)が入っている
- [ ] 外側シャドウが「大きくぼかして低不透明度」になっている(濃く小さい影は安く見える)
- [ ] 角丸が十分に大きい(パネル 20〜28px / ボタンは pill)

## C. 可読性

- [ ] 想定される **最も明るい背景** で本文 4.5:1 を満たす
- [ ] 想定される **最も暗い背景** で本文 4.5:1 を満たす
- [ ] アイコン・境界線が 3:1 を満たす
- [ ] `text-shadow` による誤魔化しをしていない
- [ ] ライト / ダーク両モードで確認済み

## D. アクセシビリティ

- [ ] `prefers-reduced-transparency: reduce` で不透明にフォールバックする
- [ ] `prefers-contrast: more` に対応している
- [ ] `prefers-reduced-motion: reduce` でモーションを止めている
- [ ] フォーカスリングがガラス上でも視認できる

## E. パフォーマンス

- [ ] 画面内の `backdrop-filter` 要素が 4 枚以下
- [ ] blur 値をアニメーションしていない(動かすのは transform / opacity のみ)
- [ ] ガラスのネストが 1 段以下
- [ ] 祖先に `filter` / `transform` が無いことを確認した
- [ ] `-webkit-backdrop-filter` を併記した
- [ ] スクロール・リサイズ時にカクつきが出ないか実機で確認した

---

## 症状別 調整早見表

| 症状 | 原因 | 対処 |
|---|---|---|
| ただの灰色の箱に見える | 背後に透かすものが無い | 背景にグラデーション/写真を敷く。無理ならガラスをやめる |
| 眠い・くすんで見える | 彩度が落ちている | `saturate()` を 180% 付近まで上げる |
| 平坦な半透明板に見える | 縁とハイライトが無い | 1px border + inset ハイライト + スペキュラを追加 |
| 文字が読みにくい | 地色が薄すぎる | `--glass-alpha` を上げる(blur を上げても改善しない) |
| 内側のパネルが濁る | ガラスの多段ネスト | 内側は半透明チップに置き換える |
| スクロールが重い | backdrop-filter が多すぎる | 枚数を減らす / blur を下げる / 固定要素のみに限定 |
| 効果が突然消える | 祖先の filter・transform | 祖先のスタイルを外すか、ガラス要素を階層外に出す |
| 影が安っぽい | 影が小さく濃い | ぼかしを大きく、不透明度を 0.15〜0.20 に下げる |

ほかの公開プロンプトも見る

Chat Core のプロンプト共有では、文章作成・画像生成・スキルなど、さまざまなカテゴリの公開プロンプトを検索・閲覧できます。

プロンプト共有ページへ

Discover more

おすすめのプロンプト

すべて見る