Blur craft(ブラークラフト)
Web上のガラスのほとんどは、次の3つの理由で安っぽく見えます。背後に面白いものがなく、マテリアルが単一の色調と単一のブラーで構成され、その上のテキストは誰も測定していない濁った灰色だからです。高級に見えるガラス(Appleのマテリアル、visionOS、最高のプロダクトサイト)は、次の3つの要素をこの順序で正しく実現しています。
- ガラスの背後にある光がデザインされている。 ガラスは背後にあるものを引き立てるので、そこに光を配置します。
- ガラスは色調ではなく、マテリアルである。 飽和したブラー、グラデーションフィル、輝く縁、スペキュラ光沢、奥行き、グレイン。それが
assets/glass.cssです。 - テキストが測定されている。 半透明のガラスは、背後にあるピクセルごとにコントラストが変化するため、コントラストはスクリプトによって最悪のポイントで、3つの状態(
scripts/glass-contrast.mjs)でチェックされます。
クイックパス
| 作りたいもの… | 使用するもの | メモ |
|---|---|---|
| スティッキーナビゲーションバー | .gs-bar (surfaces.css) | 拡張背景;gs-bar--on-scroll を追加して、スクロール後にのみガラス状にする |
| アート上のプレイヤー、ドック、ピル | .gs-dock.glass.glass--clear + liquid-glass.js | クリアLiquid Glass、画面ごとに1つ;アートが頻繁に変わる場合はアダプティブトーン |
| テキストを含むフローティングカードまたはパネル | .glass.glass--regular | 詳細な写真の上に thick |
| メニュー、ポップオーバー、コマンドバー | .gs-menu.glass | 約86%、0.5pxのトップハイライト上で32px |
| ダイアログ | .gs-veil + .gs-dialog.glass.glass--thick | 金額の確認、削除、署名時は glass--solid;ガラスクロムが下にある場合は gs-veil--flat + .gs-modal-open |
| トーストまたはボトムシート | .gs-toast.glass.glass--regular / .gs-sheet.glass.glass--thick | gs- クラスはレイアウトのみ;マテリアルは .glass から来る |
| バーの下にフェードするコンテンツ | プログレッシブブラー(レシピ2) | ビューごとに1つのスクロールエッジエフェクト |
| 到着する見出し、または変化する値 | ブラーリビール(4)/ 2pxクロスフェード(4b) | 画面ごとに1回 |
| アートの色に染まるページ | アート背景、ベイクド(レシピ8) | 固定ガラスの下でライブブラーは不可 |
| Tailwind v4プロジェクト | glass.css + glass.tailwind.css (glass-blur-24, …) | Tailwind独自の backdrop-blur-* はSonoma Safariで壊れる |
| ネイティブアプリ(SwiftUI、Flutter、React Native、Compose) | references/native.md | 同じメソッド、各ツールキットのマテリアル |
| 写真、ビデオ、デザインエディタ用のクロム | .glass.glass--thick.glass--neutral | ニュートラル:彩度ブーストなし、ガラスが作品の色を変えてはいけない |
次に:光を構成し(§1)、マテリアルを設定し(§2)、チェックします(§5)。assets/demo.html はすべてのサーフェスをコントロール付きでライブ表示します。選択する前に、各クラスの動作を確認するために開いてください。
1. 最初に光を構成する
各ガラス表面のすぐ後ろに何が来るかを決定し、それをそこでもっとも明るいものにします。
-
ガラスの下に光を配置する: グロー、アートの中の太陽、プロダクトの色、ライブのWebGLコンポーネント。ぼかした単色は同じ単色です。虚空の上のガラスはグレーのボックスです。
-
光を端にまたがらせる。 最高のガラスは、光の上と闇の上に半分ずつ位置するため、その幅全体で色が変化します。
-
縁(リム)を光に向ける。
--glass-lightを光の色(夕日なら255 200 160)に、--glass-rim-angleをその方向に設定します。リムの明るい端が光の方を向きます:光源の方向 左上 上 右上 右 右下 下 左下 左 角度 135deg 180deg 225deg 270deg 315deg 0deg 45deg 90deg ガラスの下にある光は、最も近いエッジの角度に、中心に向かって約15度加えた角度を取ります。この角度は登録された
@propertyであるため、ポインターやスクロールにスムーズに追従できます(Appleのハイライトは、光が移動するにつれてマテリアルの周りを移動します)。 -
ガラスを、それが主役であるかのようにサイズ設定する。 その下のシーンの変化を示すのに十分な大きさである場合、マテリアルとして読み取れます。Appleは、より大きなガラスをより厚いガラスとして動作させます:より深い影、よりソフトな散乱。
2. マテリアルを設定する
assets/glass.css(コピーするときは glass プレフィックスをリネーム)と assets/surfaces.css を既製のサーフェスに使用するか、コンポーネント:Glass.tsx(React)、Glass.vue(Vue 3)、Glass.svelte(Svelte 5)を使用します。1行の backdrop-filter カードを手書きしないでください。
backdrop-filter はリテラル値で、決して var() を使わず、前置詞なしを最初に、-webkit- を最後に書きます。 macOS Sonoma上のSafari 18および26は、フィルターがカスタムプロパティ(WebKit 297620、未解決)から構築されている場合、ブラーをレンダリングしません。また、Tailwind v4の backdrop-blur-* はまさにその方法で構築されています。同じバグレポートは、リテラル値であっても、そこで前置詞なしのプロパティが失敗することを示しているため、ブラウザがそれを適用する場所である、前置詞付きの宣言(-webkit-)が最後に配置されます(ChromeとFirefoxはこれを無視します)。glass.css には、厚さ×トーンごとのリテラルフィルターがあり、クラスによって切り替わります。変数は塗りつぶし、ディム、色に問題なく使用できます。
厚さ。 ガラスが運ぶテキストの量によって選択します。値は demo.html の明るい光の上でコントラストチェッカーを使用して調整されました:
| クラス | ブラー、ディム | 明るい光の上で4.5:1をパスするか? | 使用用途 |
|---|---|---|---|
glass--clear | 16px, 22% | いいえ:太字または大きなテキストとアイコンのみ | ドック、再生ボタン、メディア上のピル(Apple: クリアには太字で明るいコンテンツとディミングレイヤーが必要) |
glass--thin | 24px, 30% | 最も明るい光の上では不可 | コントロール、チップ、中程度の背景上の小さなカード |
glass--regular | 32px, 48% | キャリブレーションページではYes;プレイヤーの背後にある明るい夕日は、0.62で thick が必要だった | プレイヤー、パネル、トースト:デフォルト。ブラーオフ(色調のみ)の状態が最初に失敗することが多い |
glass--thick | 44px, 56% | はい | メニュー、シート、ダイアログ、テキストが多いもの |
glass--solid | 4px, 92% | はい | 支払い、削除、署名(約85%以上の塗りつぶしでは大きなブラーが見えないため、4px) |
インクテキストを使用するライトガラスには glass--light を、色が重要なアプリケーション(写真、ビデオ、デザインエディタ)では glass--neutral を追加します。彩度ブーストやトーンシフトはなく、ガラスが作品の見え方を変えてはいけません。詳細な写真の上では、--glass-dim: rgb(10 10 18 / 0.65–0.75)(数値ではなく色)で thick から始めます。鮮やかなガラスと読みやすいテキストはそこで互いに相反するため、鮮やかさはリム、光沢、ガラスの周りにこぼれる光に費やします。
iOS 26.1のような2つのレベル: prefers-contrast: more(Safariユーザーが到達できる設定、Safariには prefers-reduced-transparency はありません)に対して、色付きレベル(不透明度が高く、低くなることはない)が glass--tinted でオンになるか、サイト全体では <html data-glass="tinted"> でオンになります。glass.cssは、Windows High Contrast(ソリッドな Canvas サーフェス)、印刷(プレーンなボーダーボックス)、スクリーンショットツール用のキャプチャモード、RTLも処理します。
ガラスはコントロールレイヤーに属します(ナビ、ツールバー、ドック、メニュー、シート、ダイアログ)。これはコンテンツの上にフロートし、コンテンツ自体には決してならず、ガラスの上にガラスを重ねることもありません(Apple、WWDC25)。プライマリアクションのみを色付けします。ブリーフのレジスターに合わせます:没入型のブリーフは、ヒーローコントロールに強い光とクリアガラスを取ります。信頼されるもの(金融、ヘルスケア)は、厚いまたはソリッドなガラスを取り、ほとんど光を入れません。
references/material.md には残りが含まれています:各レイヤーの役割とその理由、Apple.com、Linear、Raycast、Radix、Material、Fluentから読み取ったプリセット、Appleの完全なWWDC25ルールリスト、およびレジスターテーブル。
3. シグネチャエフェクト
コードは references/recipes.md にあります:
- Liquid Glass屈折: リムが背後にあるものをレンズのように曲げ、オプションで色収差(0.6–1)を伴います。2つのバージョン:
liquid-glass.ts/.jsは任意のページコンテンツを屈折させますが、Chromiumのみ(SafariはSVG背景フィルターに何も描画しません、WebKit 245510);liquid-glass-webgl.jsは、ページ自体が描画する背景(<canvas>、<img>、<video>、例えばヒーロー壁紙など)をすべてのブラウザで屈折させ、ChromiumとWebKitでレンダリングが確認されています。それ以外の場合は、曇りマテリアル単独で完成して見える必要があります。屈折と曇りはトレードオフの関係にあります:曲がりはクリアガラスを通して見えます(blur0–6);曇りガラス(12–20)は端から端まで曇り、曲がりはソフトな色の変化になります。単語やアイコンにはクリア、文章には曇り、テキストは端からベゼル幅だけ内側に配置します。ベールの上のダイアログでは決して使用しないでください:曲げるに足るシャープなものは残っていません。 - スティッキーバー用の拡張背景: コンテンツがスクロールして下に入る前に、色がガラスに到達します。
gs-bar--on-scrollは、純粋なCSS(スクロール駆動アニメーション)で、スクロール後にのみバーをガラス状にします。 - プログレッシブブラー: コンテンツがバーの下でカットされる代わりに溶解します。CSSが
linear-blur()を取得するまで(提案中、csswg #13285)、積み重ねられたマスクレイヤーが唯一の方法です。 - ブラーブリッジドクロスフェード: 状態スワップ中の2pxブラー(Emil Kowalski)。
- ブラーリビール:
blur(8px)から、一度だけ、到着モーメントとして。 - フォーカスベール: ダイアログの後ろのページが4–8px後退します。
- ガラスモーフとプレス: 近くのガラス形状間の
layoutIdモーフ(Cursor: 0.34s、[0.32, 0.72, 0, 1])と、プレス時の内側グローパルス(スケールではありません)。 - マージングガラス形状: gooフィルターされたSVGマスクでカットされた1つのガラスレイヤー。これにより、Appleのガラスコンテナのように、近くの形状が液体のネックで結合します(レシピ11、Chromiumでテスト済み)。
- ビデオからのアンビエントグロー: 再生中のビデオの10×6キャンバスサンプルをスケールアップ(レシピ8b)。
- 着色: 構造用ガラスにはクロマ約0.03–0.05、着色には相対色アルファ(レシピ12)。
- 被写界深度、ベロシティモーションブラー、アート背景(ベイクド)、ロックされたコンテンツ、グレイン。
4. 高速に保つ
最初にルックをデザインし、次にこれらを守ります:
- 長いまたはループするアニメーションは、不透明度とトランスフォームに配置し、ブラー半径には配置しません。短時間の単発は問題ありません:Apple.comはメニューカーテンのブラーを0→20pxに320msかけてアニメーションさせています。
- 2つの積み重ねられたサーフェスを同時にブラーしないでください(Appleのナビは、フライアウトが開いている間、自身のブラーをドロップします)。ガラスクロムの上にダイアログが開くときは、
<html>に.gs-modal-openを追加し(クロムはブラーを停止し、ほぼ不透明になります)、gs-veil--flatを使用するか、画像またはキャンバスの背景からベールをベイクします。フォトエディタのテストで計測:5つのガラスパネルの上のライブ全画面ベールブラーは31fpsで実行されました。それがなければ60fpsでした。 - 固定またはスティッキーブラーは、スクロールフレームごとに再実行されます。画面ごとに1つの大きなものにし、その下に大きなブラー画像をベイクします(計測結果:ライブブラーで60→22fps、ベイクで60fpsに戻る)。
- スマートフォン:7つの18pxパネルは、Mali-G57でフレームあたり約3.5msのコストがかかります(フレームの75–80%が時間通りに対し、なしでは99%)。数パネルを超える場合は、レイアウトのスマートフォンブレークポイントで
backdrop-filterをドロップし、半透明の塗りつぶしを維持します(またはglass-tier.jsにデバイスごとに決定させます)。 - 予算はブラー半径や数ではなく、ブラー領域です。 このスキル用に計測(Chromium、2xのソフトウェアレンダリング、移動背景、vsyncオン):半径4→64px、および同じ総面積で1→9サーフェスは違いがありませんでした。画面の90%をブラーすると51fpsに低下しました(p95 33ms)。これはSkiaが大きなブラーをダウンサンプリングすることと一致しています。数値は相対的ですが(高速なMacでソフトウェアレンダリング)、ランキングは転用可能です。
htmlに不透明な背景色を与えます:Safariはその後、ガラスを含むページに対してもう1つの追加の全画面コンポジッティングレイヤーをスキップします(WebKit 271340:修正は不透明なドキュメントに対してのみレイヤーをスキップします)。- 不透明な塗りつぶしの下ではブラーをかけないでください。FramerとDiaはソリッドな背景に
backdrop-filterを出荷し、誰にも見えないブラーに対して支払いをしています。約85%以上の塗りつぶしでは、≤4pxまたはなしを使用します(Arcのトースト:85%および3px)。 - デバイスごとにガラスを階層化します:
assets/glass-tier.jsは、デバイスメモリ、Save-Data、フレームレートプローブ(iOS Low Power Modeはアニメーションを意図的に30fpsに制限します)、Compute Pressureからdata-glass-tierを full、lite(1つの8pxブラー)、flat(ブラーなし、より多くの色調)に設定します。これはAndroid、Fluent、Appleが弱いデバイスや省電力デバイスでブラーをドロップする方法と同じです。 - ビデオの上では、再生中のビデオをブラーしないでください:それを小さなキャンバスにサンプリングし(レシピ8b)、フルスクリーンではガラスをドロップします。SafariはビデオピクセルをSVGフィルターに渡すことはありません。
- 背景ルート:
opacity < 1、filter、マスク、clip-path、mix-blend-mode、backdrop-filter、またはこれらのいずれかにwill-changeを持つ親は、内部のガラスをフラット化します。これにはFramer Motionの親フェードや、ガラスブロブの親にあるgoofilterが含まれます。ガラス自体をフェードさせます。クリアリビールフィルター(filter: none)は、それらが終了したときにクリアします。 backdrop-filterは、position: fixedの子要素の包含ブロックとなる要素を作成します:ポータルメニュー、トースト、ダイアログをガラスコンテナの外に出します。- 祖先の常時
view-transition-nameは、Chromiumでガラスをフラット化します。トランジション中にのみ名前を設定します。ラッパー上のフレームワークフェードトランジションも同じことを行います:ガラス自体をフェードさせます。 - ガラスのスクリーンショット、OG画像、PDFの取得:html2canvas、Satori、printはブラーをドロップするか壊します。キャプチャ中は
<html>にdata-glass-captureを設定し(glass.cssはガラスを不透明にします)、quirks.mdを参照してください。
5. チェックする(必須)
ガラスを完成と呼ぶ前に、これらすべてを実行します:
- フロストチェック:
node <skill>/scripts/frost-check.mjs <url or file.html>は、すべてのガラスサーフェスについて、ブラーがどれだけの詳細を取り除くか(ブラーオン vs オフ)を測定します。NO BLURは、背景ルート、壊れたプレフィックス、var()、または古いLiquid Glassマップを意味します。FLATは、背後に測定するものがないことを意味します。代わりに目でチェックするには、ガラスの背後に太字の赤いテキストを配置し、deviceScaleFactor: 1でキャプチャして拡大します。 - コントラスト、測定済み、最悪の背景で:
node <skill>/scripts/glass-contrast.mjs <url or file.html>。最も明るい現実的な状態を指定します。きれいなデフォルトではありません。最も明るい写真、日光のフレーム、+2 EVにプッシュされた画像、バーの下をスクロールする白いページセクションなどです(URLパラメータまたはテスト状態を追加して、スクリプトがロードできるようにします)。あるエディタでは、デフォルトの写真は8.7:1でパスしましたが、明るいフレームは4.4:1で失敗しました。スマートフォン幅も確認します(--width 390 --height 844)。テキストを非表示にし、各行の下で最も明るいピクセルと最も暗いピクセルを見つけ、3つの状態で4.5:1(大きなテキストは3:1)をチェックします:通常、色調のみ(ブラーオフ、iOS Low Power Modeで表示されるように)、およびprefers-contrast: more。失敗を修正するには、厚さを1つ上げるか、--glass-dim(例:rgb(10 10 18 / 0.65)からrgb(10 10 18 / 0.70)へ)のアルファを上げるか、--glass-inkの彩度を下げるか(インクはガラスを通して見えるため)、またはチェックが通るまで文字のウェイトまたはサイズを大きくします。 - 最終的な手動チェック: 理想的には実機でガラスを開き、最悪の背景の下で注釈やUIテキストを読みます。スクリーンショットはガラスをフラット化し、テキストのノイズを隠します。
data-glass-captureを使用して、スクリーンショットがユーザーにどのように見えるかをテストします。ブラウザの描画と異なる場合があります。フロストチェックとコントラストチェッカーは、これに代わるものではありません。
[truncated by model, original content continues]