4 ポイント 投稿者 GN⁺ 2024-11-25 | 1件のコメント | WhatsAppで共有
  • 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-filterblurを適用して実装する
  • 基本となるガラス要素は単純な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方式では、::beforebackground-attachment: fixedを追加する
    • 実装は簡単だが、すべてのプラットフォームで動作するとは限らない
  • すべてのプラットフォームで動かすには、JavaScriptでbackground-attachment: fixedを模倣する
    • JavaScriptから::beforeを直接扱う方法は非効率なため、別のdiv.light要素を使う
    • 対象要素にはdata-js-background-attachment-fixed属性を付ける
  • JavaScriptは各アニメーションフレームごとに対象要素のgetBoundingClientRect()値を読み取り、ビューポート内の位置と逆方向に**background-position**を更新する
    • backgroundPositionX = -clientRect.x
    • backgroundPositionY = -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: repeat
    • background-size: 750px
    • opacity: 0.075
    • position: absoluteと四方向オフセット0で親全体を満たす
    • z-index: -1で他の子要素の背後に描画する
  • .drag-meはコンテンツを中央揃えにし、色付きの半透明ガラスレイヤーを作る
    • display: flex
    • align-items: center
    • justify-content: center
    • height: 30px
    • background-color: rgba(12, 13, 14, 0.75)

JavaScriptなし版の違い

  • JavaScriptなし版では、別個の.light要素の代わりに.glass::beforeを使う
  • ::beforeに光線画像を適用し、background-attachment: fixedで画面に固定された反射を実装する
  • この方式はすべてのプラットフォームで動作するわけではなく、JavaScript版ではこれを補うためにbackground-positionを直接更新する

1件のコメント

 
GN⁺ 2024-11-25
Hacker News のコメント
  • 美学的には本当に気に入っているが、端のあたりでは物理的に合わない部分がある
    組み込み開発者の視点では、少し無駄が多いように感じる。すべてのクライアントが、背景画像のぼかした版と合成するために、毎回「高価な」ブラー・フィルターを計算しているようなものではないかと思う
    GPU を使っていて最適化されているので、結局大きなコストではないのかもしれないが、最近の Web 開発は全体として肥大化しすぎる流れに見える。単純なサイトでも 5 秒ずつ読み込み、重い処理をクライアントに押しつけるような形だ。もちろん、これはこの記事の筆者の責任ではない

    • 何を無駄と見るかには、それぞれの先入観があるように思う
      14.4k モデムの時代に育ったので、ネットワーク帯域は CPU 時間よりはるかに希少で高価だと考えることに慣れている
      クライアント側で簡単に計算できるなら、インターネット越しに画像全体をダウンロードするほうが無駄だと思う。その画像を受け取るためにルーター、サーバー、遠くにあるディスクまで動かすことになるが、すでにクライアントの RAM にあるデータを一度処理するのを避けるためにそこまで使うほうが、よほどもったいない
    • 技術的にある面で「無駄が多い」Web サイトも、実際の用途を見れば、大きく見ればほとんどが純粋な娯楽に使われている
      だから娯楽そのものが無駄なのか、そうでないなら娯楽をより良くするために計算を余分に使うのも構わないと思う
    • 人間の目には「レンダリング済みのグラフィックを大きく再計算している」ように見えて無駄に感じるが、技術的には必ずしもそうではないと思う
      UI で変わるものを再描画するには、いずれにせよ GPU の計算が必要で、単純なブラーはかなり効率よく追加できる。GPU レイヤーとして最適化されていない DOM オブジェクトのアニメーションより、コストは低い可能性が高い
      最近は最も単純なサイトでも1MB 以上の JavaScriptと大量のトラッカーを読み込んで CPU を食っていることを考えると、美的効果のためのブラーは無駄リストのかなり下のほうだと思う
    • ぼかした画像と元画像の両方をネットワークで送るやり方こそ、過去 20 年間の Web 開発でやってきたことではないかと思う
      高解像度画像が多い場合、実際のネットワーク帯域は有限で、特に無線カバレッジの悪いモバイル環境では、ローカル計算より明らかに性能が落ちる。最近は CSS/WebGL だけでできることが驚くほど多く、以前はこうした効果のために多くのハックや回避策が必要だった
    • 今こそ、「おお、格好いい。きっと自分/自分たちには必要だ」といった技術のかなりの部分は、この世に居場所がないのだと真剣に受け止めるべきだと思う
      行為そのものが無駄かどうかとは別に、こうした考え方自体が社会のより大きな問題を示している。なぜこれが必要なのか、なぜこれがない状態を悪いと見なすのか?
      今日の社会問題の規模を考えると、UI パネルがぼやけていようがいまいが、誰が気にするのかと思う
  • Android の新しいシェーダー API で何ができるか試すために Windows 7 Aero Glass 効果を再現していたとき、似たような「光条」テクスチャを抽出したことがある
    結果的にこの記事とかなり似たものになったが、内側の影は入れず、ぼかした背景の彩度は少し上げた
    https://mastodon.social/@grishka/110524476584503201

    • とても格好いい。光条テクスチャは、この効果で実際に大きな役割を果たし得る
      正直、チュートリアル用に作ったものはそこまで素晴らしいわけでもない。Windows 7 側の、よりくっきりした線のほうが好みだ
      彩度調整も考えたし、他の例でも見たが、記事では使わないことにした。使った月の画像には色があまり多くないので、大きな差もなかっただろう。自分でガラス効果を作る人は、彩度も試してみるとよいと思う
  • 作業自体は素晴らしく、インタラクティブなデモとして見せる方法も良い。ウィンドウを月の上にドラッグしてみるのが楽しい
    ただし、ユーザーインターフェイスのデザインでフロストガラス効果を使うのは好きではなく、Mac OS に追加されたときは後退だと感じた。デザイナーはこの効果にあまりにも簡単に魅了されるが、実際には決して理想的ではない。特にパネルの背後のコンテンツが動的だったり、ユーザーが作ったものだったりする場合はなおさらだ
    2010 年代のブラッシュドメタルのような存在だが、Windows Vista から漏れ出してあらゆる場所に広がったのは驚きだ

    • なぜ「理想的ではない」のか分からない。ビジュアルデザインは、実用的な目的よりも、何が見た目に良いかという個人の好みが大きな比重を占める
      もちろんデザインは機能にも影響するが、主な目的はユーザー体験をより楽しいものにすることにある
      スキューモーフィズムは、この 10 年以上続いてきた、何もかもを平坦にするミニマルな傾向よりも、インターフェイスを楽しいものにすると考えている。現実世界の表面や素材をまねた視覚的な装飾は、親しみやすさとアクセシビリティを加えてくれる。実用面でも、フラットデザインは要素や状態を区別しにくくする一方、3D ボタン、ブラッシュドメタル、フロストガラスがあった時代のほうが、はるかに明確だった
      いまは振り子が再び戻りつつあるのだと思う。より多くのデザイナーが平坦な見た目を避けているので、より人間に優しい UI が復活することを期待している
    • UI デザイナーではないので真面目に聞きたいのだが、問題はフロストガラスやブラッシュドメタルのような美的効果を UI デザインに使うこと自体なのか、それともそうしたインターフェイスを作ろうとして、一部のデザイナーがコントロールの位置や役割を示す視覚的な手がかりを失ってしまったことなのか?
    • ターミナルウィンドウに何年も少し透明度を入れてきたが、いま考え直させられている
    • ブラッシュドメタルは情報の文脈に影響しない。ブラーは調整可能な文脈を提供する
      ブラーはたいてい正解ではないが、ときには正しい選択になる
    • 皮肉なことに、以前の macOS バージョンもブラッシュドメタルを多用していた
  • 2008年にCSSが backdrop-blur をサポートする前、似た効果を出すCSS実験をしたことがある: https://webdev.andersriggelsen.dk/aero/
    固定位置の、事前にぼかし処理した背景画像にガラス効果を重ねる方式: https://webdev.andersriggelsen.dk/aero/bgl.jpg
    リアルタイムのガウシアンブラーよりはるかに性能は良いが、動的な背景画像を許容できないという欠点はそのまま

    • さらに前の時期に、Flashファイルを背景として使って一歩進めたこともある
      動的に動けるフレーム内でもガラス効果を出せた。iframeを使ったかは覚えていないのでコードを探す必要があるが、当時を考えるとおそらく使っていた可能性が高い
    • 浮いているウィンドウが初期位置から更新されない
      Windows 10 19045.5131で、Chromeは最新のVersion 131.0.6778.86 (Official Build) (64-bit)
  • 技術的成果としては素晴らしいが、悪いUXだと思う
    半透明パネル内の内容は、一貫した単色背景上よりも読みにくく理解しにくいし、背景とのコントラストが低く不安定になる。さらに下で何かが動くと気が散り、方向感覚を乱す可能性がある

    • 単なる視覚効果ひとつを「悪いUX」と一般化するのは難しい。統合の仕方に大きく左右される
      うまく統合するなら、UIが過剰にならないよう効果の強さを調整し、ブラーをサポートしていない場合に余計な装飾を避けるため機能サポートを確認し、GPUが十分でない可能性のあるデバイスではレンダリングしないようディスプレイと映像機能を確認する必要がある
      またユーザー設定を確認して、複雑な背景が苦手なユーザーにはコントラストの高い単色を提供し、利用可能なスペースに応じて効果や影の範囲を制限し、ぼかし領域の下にある背景の複雑さとコントラストを考慮してブラーと不透明度を調整すべき
      タイポグラフィに合わせてブラーと影が適応的にスケールするよう保証することも必要。UXとは本質的に、ユーザーがアプリ全体とのインタラクションをどう体験するかの設計であって、個別のスタイル選択ひとつで成否が決まるものではない
    • Windows Vistaは、すりガラス上の黒い文字に白い影のようなアウトラインを付けることでこの問題を解決していた
      背景が黒い極端な場合でもテキストの可読性を保証する。CSSでは text-shadow プロパティで再現できる
    • だからこの効果を自分のサイト全体には使っていない。良いUXを作るのがより難しくなるから
      ただしゲームではもっと使いどころがある。特にユーザーが操作する主領域である背景を隠したくないHUDでは適している場合がある
    • コントラストが低いのが問題なら、背景やガラスの色調をより暗くして前景コンテンツをより明るくするか、その逆にすればよい
      良いコントラストは、単色でもガラス効果でも、どんなデザイン要素でも課題になる
      背景で起きていることが気を散らし、方向感覚を乱すという点も非常に主観的。単色の不透明度を下げるように、ガラスの半透明度も下げられる
      この批判は客観的に正しいとは言いにくく、そうした問題を避けながらこのデザイン要素を統合する方法はある。Forzaのスクリーンショットは良さそうに見えるし、実際に見ても背景が邪魔には感じなかった。その代わり、単色背景よりも興味深く視覚的に楽しいUIが得られる。ビデオゲームではより重要かもしれないが、OSやWebデザインでも洗練された形で使える
    • ブラーは、文脈を調整可能な程度に保ちながら情報を隠す方法
      多くの文脈が必要ならブラーは良い選択ではないし、文脈がまったく不要な場合も良い選択ではない
      しかし、時には素晴らしい選択になる
  • インタラクティブな例は良いが、前の段階と横並びで比較したり切り替えたりできるトグルがあればもっと良かったと思う
    ほとんどの段階で改善があまりに微妙で、違いを見分けにくかった

    • 同意。モバイルでは2段階目以降、違いがほとんど見えないか、まったく分からない
  • 効果が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には永遠に理解できない何らかのレベルがあるように感じる。このデモがまさにそれで、この人は霜のついた窓を作っているのに、私はいまだに div 1つを中央揃えにできない。

    • Web開発がどう動いているのかを学んでいた頃、div をもう1つ追加するのがしばしば良い考えだということを苦労して学んだ。
      最近のWebサイトの多くを見ると、div が巨大な山のように積み重なっている。中央揃えされた div が欲しいなら、その中に、中央揃えするための領域全体を占める div をもう1つ作れば比較的簡単になる。
      多くの視覚的トリックも似たようなものだが、この例はとてもクリーンなので、より印象的だ。
  • 正確には霜のついたガラスではないが、https://www.gyan.dev/ffmpeg/builds/ のサイドバーにガラス窓効果を入れてみた。

    • PCで見ると、サイトがとても落ち着いていてきれい。