ゲームからWebへ拡張されたFrosted Glass技術
(tyleo.com)- Forza Horizon 3とForza Motorsport 7のfrosted acrylic UIに着想を得て、Webでも似たガラスパネル効果をHTML/CSS/JavaScriptで再現する過程を整理している
- 効果の中心はGaussian blurであり、CSS
backdrop-filterとiOS向けの-webkit-backdrop-filterを併用することでブラウザ間の差を減らせる - 単なるぼかしだけでは平板に見えるため、
box-shadow: insetでエッジの深みとsubsurface scatteringを加え、通常のシャドウで背景の上に浮いている感覚を作る - 表面反射は光線画像を別レイヤーに敷いて実装し、
background-attachment: fixedやJavaScriptによってガラスの移動に合わせた動的な反射を模倣する - 最終UIは
.glass、.light、.drag-meレイヤーを組み合わせ、角丸、クリッピング、半透明の背景色を加えて、コピーして使えるガラスコンポーネントとして完成する
ゲームUIから持ち込んだガラスパネル効果
- Forza Horizon 3とForza Motorsport 7のUI開発経験で見たfrosted acrylicデザインをHTMLで再現することが目的
- 結果物はドラッグ可能なガラスパネルで、背景ぼかし、エッジの深み、光の反射、角丸、半透明のカラーレイヤーを備える
- 冒頭ではそのままコピーして使える最終レシピを提示し、その後で各効果を段階的に積み上げていく
背景ぼかしを作るbackdrop-filter
- 良いfrosted glass効果の核心は、背景をぼかして半透明のスクリーンのように見せるGaussian blurにある
- CSSでは
backdrop-filterにblurを適用して実装する - 基本となるガラス要素は単純な
divと.glassクラスから始まるbackdrop-filter: blur(10px)-webkit-backdrop-filter: blur(10px)
- iOSでは特別な設定を深く変更しない限り、
-webkit-backdrop-filterが必要になる backdrop-filterは比較的最近になってブラウザ対応が進んだため、Internet Explorerユーザーはデモを体験できない
エッジとシャドウで奥行きを作る
backdrop-filter: blur(10px)だけを適用すると、ガラスが平坦で単調に見えることがある- エッジは
border: 1px solidの代わりに**box-shadow: inset**で表現するborderは要素サイズや子要素の配置に影響するbox-shadow: insetを使えば、子要素が負のマージンなどの調整なしにガラスのコンテンツ領域を自然に満たせる
- 2つの半透明な白いinset shadowでガラスの縁を表現する
- 1つ目のshadowは外側から見えるガラスの角を表し、例では下辺と左辺に現れる
- 2つ目のshadowはガラス越しに見える縁を表し、例では上辺と右辺に現れる
- ガラス越しに見える縁は光が弱まるため、より柔らかく透明に設定する
- 通常の暗い
box-shadowを追加すると、ガラスが背景から物理的に浮いているような感覚を与えられる
光の散乱と表面反射
- ガラス内部に光が広がる感覚は、
subsurface scatteringを簡略化して表現している - 実装には再び
box-shadow: insetを使う- 短い散乱効果:
inset 0px 0px 10px 5px rgba(255, 255, 255, 0.025) - より深い散乱効果:
inset 0px 0px 40px 5px rgba(255, 255, 255, 0.025)
- 短い散乱効果:
- この効果は、暗い背景の上でガラスをドラッグしたときによりよく見える
- 背景がぼけて屈折しているような印象に加えて、ガラス表面で光が反射する性質も追加する
- 光の反射は、光線画像を背景として重ねることで実装する
- 類似画像を自作する際に参考になるYouTubeチュートリアルとテキスト解説がある
- 画像を
.glass要素のbackground-imageに直接入れると、backdrop-filterが画像までぼかしてしまうため、::beforeのような別レイヤーを使う
静的な反射を動的に変える
- 光線画像を重ねるだけでも反射は生まれるが、ガラスを動かしても光がガラス表面に固定されているように見えることがある
- 純粋なCSS方式では、
::beforeにbackground-attachment: fixedを追加する- 実装は簡単だが、すべてのプラットフォームで動作するとは限らない
- すべてのプラットフォームで動かすには、JavaScriptで
background-attachment: fixedを模倣する- JavaScriptから
::beforeを直接扱う方法は非効率なため、別のdiv.light要素を使う - 対象要素には
data-js-background-attachment-fixed属性を付ける
- JavaScriptから
- JavaScriptは各アニメーションフレームごとに対象要素の
getBoundingClientRect()値を読み取り、ビューポート内の位置と逆方向に**background-position**を更新するbackgroundPositionX = -clientRect.xbackgroundPositionY = -clientRect.y
- 反復ループは
requestAnimationFrameで実行される
最終的なHTML/CSS構成
- JavaScript版の最終HTMLは、
.glassの中に光反射用の.lightと、テキスト/カラーレイヤーである.drag-meを入れる構造になっている
Drag Me
.glassはガラスパネルの基本形状と視覚効果を担当するbackdrop-filterと-webkit-backdrop-filterで背景ぼかしを適用- 複数の
box-shadowでエッジ、シャドウ、散乱効果を適用 position: relativeで子レイヤーが親領域を満たせるようにするborder-radius: 5pxで角丸を適用overflow: hiddenで子要素が角丸の外へはみ出さないように切り取る
.lightは光線画像を繰り返し背景として使うbackground-image: url(path/to/light.png)background-repeat: repeatbackground-size: 750pxopacity: 0.075position: absoluteと四方向オフセット0で親全体を満たすz-index: -1で他の子要素の背後に描画する
.drag-meはコンテンツを中央揃えにし、色付きの半透明ガラスレイヤーを作るdisplay: flexalign-items: centerjustify-content: centerheight: 30pxbackground-color: rgba(12, 13, 14, 0.75)
JavaScriptなし版の違い
- JavaScriptなし版では、別個の
.light要素の代わりに.glass::beforeを使う ::beforeに光線画像を適用し、background-attachment: fixedで画面に固定された反射を実装する- この方式はすべてのプラットフォームで動作するわけではなく、JavaScript版ではこれを補うために
background-positionを直接更新する
1件のコメント
Hacker News のコメント
美学的には本当に気に入っているが、端のあたりでは物理的に合わない部分がある
組み込み開発者の視点では、少し無駄が多いように感じる。すべてのクライアントが、背景画像のぼかした版と合成するために、毎回「高価な」ブラー・フィルターを計算しているようなものではないかと思う
GPU を使っていて最適化されているので、結局大きなコストではないのかもしれないが、最近の Web 開発は全体として肥大化しすぎる流れに見える。単純なサイトでも 5 秒ずつ読み込み、重い処理をクライアントに押しつけるような形だ。もちろん、これはこの記事の筆者の責任ではない
14.4k モデムの時代に育ったので、ネットワーク帯域は CPU 時間よりはるかに希少で高価だと考えることに慣れている
クライアント側で簡単に計算できるなら、インターネット越しに画像全体をダウンロードするほうが無駄だと思う。その画像を受け取るためにルーター、サーバー、遠くにあるディスクまで動かすことになるが、すでにクライアントの RAM にあるデータを一度処理するのを避けるためにそこまで使うほうが、よほどもったいない
だから娯楽そのものが無駄なのか、そうでないなら娯楽をより良くするために計算を余分に使うのも構わないと思う
UI で変わるものを再描画するには、いずれにせよ GPU の計算が必要で、単純なブラーはかなり効率よく追加できる。GPU レイヤーとして最適化されていない DOM オブジェクトのアニメーションより、コストは低い可能性が高い
最近は最も単純なサイトでも1MB 以上の JavaScriptと大量のトラッカーを読み込んで CPU を食っていることを考えると、美的効果のためのブラーは無駄リストのかなり下のほうだと思う
高解像度画像が多い場合、実際のネットワーク帯域は有限で、特に無線カバレッジの悪いモバイル環境では、ローカル計算より明らかに性能が落ちる。最近は CSS/WebGL だけでできることが驚くほど多く、以前はこうした効果のために多くのハックや回避策が必要だった
行為そのものが無駄かどうかとは別に、こうした考え方自体が社会のより大きな問題を示している。なぜこれが必要なのか、なぜこれがない状態を悪いと見なすのか?
今日の社会問題の規模を考えると、UI パネルがぼやけていようがいまいが、誰が気にするのかと思う
Android の新しいシェーダー API で何ができるか試すために Windows 7 Aero Glass 効果を再現していたとき、似たような「光条」テクスチャを抽出したことがある
結果的にこの記事とかなり似たものになったが、内側の影は入れず、ぼかした背景の彩度は少し上げた
https://mastodon.social/@grishka/110524476584503201
正直、チュートリアル用に作ったものはそこまで素晴らしいわけでもない。Windows 7 側の、よりくっきりした線のほうが好みだ
彩度調整も考えたし、他の例でも見たが、記事では使わないことにした。使った月の画像には色があまり多くないので、大きな差もなかっただろう。自分でガラス効果を作る人は、彩度も試してみるとよいと思う
作業自体は素晴らしく、インタラクティブなデモとして見せる方法も良い。ウィンドウを月の上にドラッグしてみるのが楽しい
ただし、ユーザーインターフェイスのデザインでフロストガラス効果を使うのは好きではなく、Mac OS に追加されたときは後退だと感じた。デザイナーはこの効果にあまりにも簡単に魅了されるが、実際には決して理想的ではない。特にパネルの背後のコンテンツが動的だったり、ユーザーが作ったものだったりする場合はなおさらだ
2010 年代のブラッシュドメタルのような存在だが、Windows Vista から漏れ出してあらゆる場所に広がったのは驚きだ
もちろんデザインは機能にも影響するが、主な目的はユーザー体験をより楽しいものにすることにある
スキューモーフィズムは、この 10 年以上続いてきた、何もかもを平坦にするミニマルな傾向よりも、インターフェイスを楽しいものにすると考えている。現実世界の表面や素材をまねた視覚的な装飾は、親しみやすさとアクセシビリティを加えてくれる。実用面でも、フラットデザインは要素や状態を区別しにくくする一方、3D ボタン、ブラッシュドメタル、フロストガラスがあった時代のほうが、はるかに明確だった
いまは振り子が再び戻りつつあるのだと思う。より多くのデザイナーが平坦な見た目を避けているので、より人間に優しい UI が復活することを期待している
ブラーはたいてい正解ではないが、ときには正しい選択になる
2008年にCSSが
backdrop-blurをサポートする前、似た効果を出すCSS実験をしたことがある: https://webdev.andersriggelsen.dk/aero/固定位置の、事前にぼかし処理した背景画像にガラス効果を重ねる方式: https://webdev.andersriggelsen.dk/aero/bgl.jpg
リアルタイムのガウシアンブラーよりはるかに性能は良いが、動的な背景画像を許容できないという欠点はそのまま
動的に動けるフレーム内でもガラス効果を出せた。iframeを使ったかは覚えていないのでコードを探す必要があるが、当時を考えるとおそらく使っていた可能性が高い
Windows 10 19045.5131で、Chromeは最新のVersion 131.0.6778.86 (Official Build) (64-bit)
技術的成果としては素晴らしいが、悪いUXだと思う
半透明パネル内の内容は、一貫した単色背景上よりも読みにくく理解しにくいし、背景とのコントラストが低く不安定になる。さらに下で何かが動くと気が散り、方向感覚を乱す可能性がある
うまく統合するなら、UIが過剰にならないよう効果の強さを調整し、ブラーをサポートしていない場合に余計な装飾を避けるため機能サポートを確認し、GPUが十分でない可能性のあるデバイスではレンダリングしないようディスプレイと映像機能を確認する必要がある
またユーザー設定を確認して、複雑な背景が苦手なユーザーにはコントラストの高い単色を提供し、利用可能なスペースに応じて効果や影の範囲を制限し、ぼかし領域の下にある背景の複雑さとコントラストを考慮してブラーと不透明度を調整すべき
タイポグラフィに合わせてブラーと影が適応的にスケールするよう保証することも必要。UXとは本質的に、ユーザーがアプリ全体とのインタラクションをどう体験するかの設計であって、個別のスタイル選択ひとつで成否が決まるものではない
背景が黒い極端な場合でもテキストの可読性を保証する。CSSでは
text-shadowプロパティで再現できるただしゲームではもっと使いどころがある。特にユーザーが操作する主領域である背景を隠したくないHUDでは適している場合がある
良いコントラストは、単色でもガラス効果でも、どんなデザイン要素でも課題になる
背景で起きていることが気を散らし、方向感覚を乱すという点も非常に主観的。単色の不透明度を下げるように、ガラスの半透明度も下げられる
この批判は客観的に正しいとは言いにくく、そうした問題を避けながらこのデザイン要素を統合する方法はある。Forzaのスクリーンショットは良さそうに見えるし、実際に見ても背景が邪魔には感じなかった。その代わり、単色背景よりも興味深く視覚的に楽しいUIが得られる。ビデオゲームではより重要かもしれないが、OSやWebデザインでも洗練された形で使える
多くの文脈が必要ならブラーは良い選択ではないし、文脈がまったく不要な場合も良い選択ではない
しかし、時には素晴らしい選択になる
インタラクティブな例は良いが、前の段階と横並びで比較したり切り替えたりできるトグルがあればもっと良かったと思う
ほとんどの段階で改善があまりに微妙で、違いを見分けにくかった
効果が10個ほど重なっているが、最も厳密な美学を狙う場合でなければ7個くらいは過剰
背景色、ブラー、影や境界線くらいで十分
3段階目だけでも、ブラーと影だけでかなり良いガラス片になる。個人的には、そこに静的な光筋の画像を混ぜるのを勧める。ほとんどのアプリケーションには完全なJavaScript効果は必要ないと思う。面白いが、気が散る可能性がある
ブラー、影、光筋だけでも、いちばん上のForza画像にかなり近づける
皆がフラットデザインへ向かった理由のひとつがそれだと思う。Windows Vistaとガラス効果は格好良かったが、計算コストが大きかった
フラットデザインは美学的に議論があり、特に高齢ユーザーにとってはスキューモーフィックデザインより使いにくい場合がある [0][1]
現実感が使いやすさを助けるなら、こうした効果をWebで使うのは十分に妥当だと思う
[0]: https://www.tandfonline.com/doi/abs/10.1080/0144929X.2020.18...
[1]: https://www.sciencedirect.com/science/article/abs/pii/S01419...
n <= 3と見る理由が何なのか気になるアクセシビリティの問題なのか、性能の問題なのか、保守性の問題なのか、それとも別の理由なのか分からない
開発スキルの中でCSSが圧倒的に最も弱いので、ベストプラクティスと悪い例をまったく知らない状態
完全に一周して戻ってきた感じで興味深い
初期のCSSデモのひとつ、CSS 1向けのデモがすりガラス効果だった: https://meyerweb.com/eric/css/edge/complexspiral/glassy.html
正直、かなり印象的。CSSがどれほど創造的で強力になり得るかを見るのはいつも楽しい。
ただ、HTML/CSSには永遠に理解できない何らかのレベルがあるように感じる。このデモがまさにそれで、この人は霜のついた窓を作っているのに、私はいまだに
div1つを中央揃えにできない。divをもう1つ追加するのがしばしば良い考えだということを苦労して学んだ。最近のWebサイトの多くを見ると、
divが巨大な山のように積み重なっている。中央揃えされたdivが欲しいなら、その中に、中央揃えするための領域全体を占めるdivをもう1つ作れば比較的簡単になる。多くの視覚的トリックも似たようなものだが、この例はとてもクリーンなので、より印象的だ。
正確には霜のついたガラスではないが、https://www.gyan.dev/ffmpeg/builds/ のサイドバーにガラス窓効果を入れてみた。