世界を動かす技術を、日本語で。

ブラウザにおける液体ガラス:CSSとSVGによる屈折

概要

  • AppleのLiquid Glassエフェクト をWebで再現する技術解説
  • CSS・SVGディスプレイスメントマップ ・屈折計算を活用した実装方法
  • Snellの法則 を基礎に光の屈折挙動をシミュレーション
  • 円形ガラス表面 を例に、変位ベクトルフィールドを作成
  • SVGフィルター活用手順 とマッピング方法の詳細解説

Apple Liquid GlassエフェクトをWebで再現する

  • AppleがWWDC 2025で発表したLiquid Glass は、曲面ガラスのような屈折・ハイライトを持つUIエフェクト
  • 本記事では CSS・SVG・物理ベース屈折計算 を使い、Web上で近似再現する手法を解説
  • ピクセル単位の完全再現ではなく、コアとなる屈折・ハイライト表現にフォーカスしたプロトタイプ構築
  • 光の屈折現象 を物理法則から解説し、段階的に実装手順を紹介

屈折現象の基礎とSnellの法則

  • 屈折 とは、光が異なる媒質(例: 空気→ガラス)を通過する際に進行方向が変化する現象
  • 光の進行速度が媒質ごとに異なるため、 入射角と屈折角 の関係が生まれる
  • Snellの法則: n₁sinθ₁ = n₂sinθ₂
    • n₁: 第一媒質の屈折率
    • θ₁: 入射角
    • n₂: 第二媒質の屈折率
    • θ₂: 屈折角
  • n₂=n₁なら光は直進、n₂>n₁なら法線方向に曲がり、n₂<n₁なら法線から離れて曲がる
  • 入射角が大きい場合は 全反射 が発生する場合もある

本プロジェクトの制約事項

  • 媒質は空気(屈折率1.0)とガラス(1.5) のみを想定
  • 屈折は1回のみ (複数回の屈折や出射は無視)
  • 入射光は背景面に垂直 (パースなし)
  • 2D形状(円形のみ) を対象とし、背景面とガラスの間に隙間なし
  • これらの制約により、 Snellの法則に基づく計算を簡略化

ガラス表面の定義と表面関数

  • ガラス表面は 数式関数で定義 し、ベゼル端から中心までの厚みを表現
  • height = f(distanceFromSide) で各点の高さを算出
  • 法線ベクトル は微分値を-90度回転して求める
  • 例:
    • Convex Circle: y = √((1 - (1 - x))²)(球面ドーム)
    • Convex Squircle: y = ⁴√((1 - (1 - x))⁴)(Apple風スクイークル、滑らかな曲率遷移)
    • Concave: y = 1 - Convex(x)(凹型、外側へ屈折)
    • Lipy: ConvexとConcaveをSmootherstepでブレンド(中央が浅いリム形状)

シミュレーションと屈折ベクトル

  • 各表面関数ごとに 光線の屈折シミュレーション を実施
  • 凹面は光を外側に、凸面は内側に曲げる傾向
  • Apple Liquid Glassは主に凸面プロファイル を採用
  • 対称性を利用し、ベゼルからの距離ごとに変位量を事前計算 して再利用

変位ベクトルフィールドの作成

  • ガラス表面全体の変位ベクトルフィールド を計算
  • 円形の場合、変位方向は常に境界に直交
  • 半径上を127分割してサンプリング (SVGマップ解像度制約)

ベクトルの正規化と最大変位量

  • 最大変位量で正規化 し、全ベクトルの最大値を1.0にスケーリング
  • displacementVector_normalized = { angle, magnitude / maximumDisplacement }
  • 最大変位量はSVGフィルタのscale値として利用

SVGディスプレイスメントマップの生成

  • SVGの<feDisplacementMap /> で屈折を表現

  • ディスプレイスメントマップは 32bit RGBA画像 で表現

    • R: X軸変位、G: Y軸変位、B/Aは無視
    • 8bit(0–255)で-128~127ピクセルの範囲を表現
  • scale属性 で実際のピクセルシフト量を調整

    <svg colorInterpolationFilters="sRGB">
      <filter id={id}>
        <feImage href={displacementMapDataUrl} x={0} y={0} width={width} height={height} result="displacement_map" />
        <feDisplacementMap
          in="SourceGraphic"
          in2="displacement_map"
          scale={maximumDisplacement}
          xChannelSelector="R"
          yChannelSelector="G"
        />
      </filter>
    </svg>
    

ベクトル→RGBA値の変換

  • 極座標(角度・大きさ)→直交座標(X・Y) に変換

  • 正規化済みベクトルを0~255の範囲にマッピング

    const x = Math.cos(angle) * magnitude;
    const y = Math.sin(angle) * magnitude;
    const result = {
      r: 128 + x * 127,
      g: 128 + y * 127,
      b: 128, // Blueは未使用
      a: 255, // Alphaは常に不透明
    };
    

Playgroundと最終レンダリング

  • Playgroundで表面形状・ベゼル幅・厚み・スケールを調整可能
  • 入力値に応じて 屈折フィールド・ディスプレイスメントマップ・最終描画 が変化
  • Apple Liquid Glass風UIエフェクトのWeb再現 を体験可能

このように、 物理ベースの屈折計算とSVGフィルタ を組み合わせることで、Apple Liquid Glassのような 没入感あるガラスUIエフェクト をWeb上で実現可能。 CSSやSVGの知識に加え、光学的理解 が重要なポイント。

Hackerたちの意見

これに似たものをWebGLシェーダーで作ったことがあるよ(ブラウザ間で動くのが利点)。リアルなHTML要素を背後で屈折させるのが難しかったけどね。 https://real-glass.vercel.app

すごい!

かっこいい!これ、分散効果もあるみたいだね。つまり、ガラスの端で色が分かれるってことだ。

テキストの上にガラスを動かしたときに、ゴーストや遅延が起きる原因は何?

見た目はいいね!でも実際に使うには遅すぎる。OPのはもっとスムーズだよ。

すごいけど、例をスクロールしてると、フルロードしたM4-MaxのMacBook Proがカクカクするのが印象的。これをフルUIで使ったらパフォーマンスがどうなるか想像したくないな。AppleはUIで最適化をめちゃくちゃやってるから、できるんだろうね。

同じく、うちのマシンでもすごくラグい。スペクタキュラーなボーダーエフェクトも動かなかったよ。

そうだね、このサイトはスムーズにはスクロールしない。けど、ほとんどのケースでCSSがGPUを活用できるとは思えない。AppleはUIを処理するためにシリコンに何かを組み込んでるに違いない。

ハハ、投稿者だよ。ここに投稿する前にパフォーマンスの問題を直そうと思ってたんだけど(HNがすぐ指摘するのを知ってたから)、誰かが先に投稿しちゃった。君の言う通り、今はかなり遅いし最適化が必要だね。屈折や変位マップだけじゃなくて、ビジュアライゼーションの部分もまだ最適化されてないし。

ちょっとパフォーマンスを改善したよ。これで少しは良くなったはず、少なくともChromeではね。(SafariはまだSVGのレンダリングがちょっと遅いみたい)それにしても、このブログ記事がHNに載るとは思ってなかったから、まだ改善点があるね。

液体ガラスのためのJSライブラリをフォークして、ポジショニングの修正を加えたよ。プレゼンで使うと楽しい。 https://github.com/nkzw-tech/liquid-glass

いいね!君の方が好きだな。

今まで見た中で、ガラスのブラウザ実装としては一番印象的だね。ただ、互換性やパフォーマンスの問題で「リアル」なウェブサイトでは使えなさそうだけど。

すごく近いけど、まだダメ。拡大鏡の効果でテキストがちょっと歪んで、本物と比べると違和感がある。displacementの「l」がすごく傾いてるし、レンズを動かすと角度も変わる。https://i.imgur.com/PW4RAYq.png

液体ガラスが前の光沢のあるガラスデザインと比べて実際に機能する理由は、コントラストのための自動色調調整だね。これを実現してるのは見たことないよ。

Chrome専用デモ 現在、最後のインタラクティブデモはChromeでしか動かないよ(SVGフィルターをバックドロップフィルターとして使ってるから)。他のブラウザでも記事は読めるし、インラインシミュレーションともやり取りできるよ。お前の家族全員に恥を!お前に恥を、お前の牛にも恥を…

同じ反応だったけど、変なのはFirefoxでは普通に見えたんだよね…?

Firefoxでは問題なく動くよ。

Liquid Glassはあんまり好きじゃないけど、これはめっちゃすごいね!

最初にFirefoxでデモを試したとき、「わぁ、これおしゃれだな」って思ったんだ。でも、「Chrome専用」って警告が出てきてさ。正直、Firefoxの見た目の方が好きなんだよね。

どれも使えそうに見えないな。デジタル家族写真にはぴったりだけど。記事は素晴らしかったよ。