Web Liquid Glass
一個用於網站的生產級玻璃材質,取自一個實際運行的 Next.js + Tailwind 網站。完整的工作原始碼位於 reference/ 目錄中:
reference/liquid-glass.css:整個材質(標記、表面、變體、形狀玻璃、折射、退化)。約 2,200 行,包含詳細說明每個值的註解。請閱讀您需要的部分,而非整個檔案。reference/glass.tsx:<Glass>React 元件和 SVG 折射濾鏡。reference/glass-specular.tsx:追蹤指標和傾斜的高光元件。
該參考檔案引入了兩個網站輔助函式(cn 和來自輕量模式的 LITE_CLASS)。請替換為專案自己的 cn/clsx,以及一個用於「關閉效果」的類別名稱。命名為 sky-*、kiosk-* 以及與祈禱相關的選擇器是特定於網站的變體範例。可以刪除它們或將其用作模式。
什麼是玻璃
玻璃有四個部分。如果網頁版本只實現了第一部分,看起來會很廉價:
- 材質:模糊加上飽和度提升(約 200%)。低於 150% 時,它看起來像灰色塑膠。加入亮度提升和對比度調整,使後方雜亂的內容擴散成柔和的洗白效果。
- 邊緣:光線照射邊緣形成的明亮細線,對側邊緣較暗。沒有邊緣的模糊永遠不會看起來像玻璃。
- 光澤:頂部邊緣內側的柔和鏡面高光。
- 深度:一個寬廣、非常柔和、低透明度的陰影,而非緊湊的卡片陰影。
折射(內容在邊緣處彎曲)是第五個部分,也是網頁唯一無法低成本實現的部分。它需要 backdrop-filter: url(#svg-filter),這僅在 Chromium 瀏覽器中有效。
玻璃的應用位置
將玻璃放在導覽層(欄位、膠囊導覽、浮動控制項、工作表)上,而不是主體內容上。玻璃上的文字對比度取決於其後方滾動的內容,因此無法保證。保持不透明卡片作為內容的默認值,並使玻璃成為每個表面的選擇性加入選項(.lg)。
耗費實際時間的規則
- 玻璃 CSS 必須與
@tailwind base位於同一個檔案中,並放在@layer內部。 Tailwind 按檔案解析@layer,因此單獨的 CSS 檔案會在@layer base上報錯。移除包裝會使規則成為非分層規則,而非分層規則會覆蓋所有 Tailwind 工具類別。.lg { position: relative }會默默地覆蓋導覽列上的fixed。 - 切勿編寫
--x: calc(var(--x) * 0.7)。 這是一個循環:在計算值時無效,它會默默地回退到繼承值,且不會報錯。請使用第二個變數(例如--lg-clarity-bump、--lg-press)。 - 一個玻璃表面只有一條邊緣,由
::before繪製。 兩條邊緣(::before邊緣加上內嵌的box-shadow斜面,或邊框盒外部的擴散陰影)會產生「雙重邊框」,無論如何調整透明度都無法修復。 corner-shape不會被繼承。 當表面使用corner-shape: squircle時,每個在邊界上繪製的偽元素都需要同時使用border-radius: inherit和corner-shape: inherit,否則邊緣會遵循與主體不同的曲線。- 巢狀玻璃內部不要使用
backdrop-filter。 它會取樣已經被著色的背景,導致渾濁。玻璃欄內部的選取晶片(.lg-chip)是一個有著色但自身沒有模糊的透鏡。 - 不要在
:root上動畫繼承的自訂屬性。 它會使整個文件的樣式失效:在一個有 60 個表面的頁面上,每幀大約花費 11.6 毫秒,而對每個元素寫入相同值則只需 2 毫秒。 - 導覽列在每次滾動時都會重新模糊。 為
.lg-bar設定較小的模糊半徑並加上contain: paint。如果裝置仍然卡頓,請設定--lg-blur-bar: 0px;邊緣和光澤承擔了大部分視覺效果。 - 不要為了修復一個瑕疵而將磨砂玻璃扁平化。 一個接近不透明的「純色」欄位會失去玻璃的外觀。相反地,請找出幾何原因(遮罩使邊緣處的主體變薄,雙重邊緣)。
- SVG 折射透鏡絕不能取樣超出其自身邊框的範圍。 Chrome 在該處會回傳透明像素,導致原始內容以鬼影形式顯現。
Safari 和 iPhone
WebKit 支援 backdrop-filter,但拒絕在其內部使用 SVG 濾鏡,因此 Safari 獲得的效果少於 Chrome:永遠不會有折射。Safari 能夠折射的是它自己的工具欄。請設定 viewportFit: "cover" 以使頁面在其下方運行,然後 env(safe-area-inset-*) 在導覽列和頁腳上成為強制性的。
無障礙與降級方案(務必提供)
每個表面都必須降級為一個接近不透明的著色,看起來相似且每幀成本為零:
@media (prefers-reduced-transparency: reduce)@supports not (backdrop-filter: blur(1px))@media (prefers-contrast: more):更強的著色和實心邊緣- 一個根類別,例如
.lg-off,一次性關閉所有玻璃表面(用於使用者切換或低功耗模式)
為導覽列提供其自身的更高最大著色值(--lg-tint-max-bar),以便在內容在其下方滾動時,導覽連結仍能保持文字對比度。
如何應用
- 從
reference/liquid-glass.css複製標記區塊和表面部分到專案的主要 CSS 檔案中,放在其現有的@layer區塊內(規則 1)。 - 將顏色標記映射到專案的調色板。參考檔案使用 shadcn 風格的
hsl(var(--card))標記。 - 使用來自
reference/glass.tsx的<Glass>元件,或直接使用.lg、.lg-bar、.lg-nav、.lg-pane、.lg-chip和.lg-refract類別。 - 僅在值得其成本的地方(例如主要控制項、主導覽列)加入來自
reference/glass-specular.tsx的鏡面高光,並尊重prefers-reduced-motion。 - 同時在 Chrome 和 Safari 中檢查,在淺色和深色模式下,以及在有複雜圖片的背景和純文字背景上進行測試。
現成的控制項:Glisse
Glisse 由 Kelvin Zhang 開發(npm install glisse,MIT 授權,React 18+,無其他依賴),提供了互動式的液態玻璃控制項,內建按壓提升為透鏡的行為:Button、Switch、Slider、TabBar、SegmentedControl、Menu、Input、SearchField 和一個純 Glass 表面。其樣式由 JS 套件注入,因此無需匯入 CSS 檔案。
何時使用哪一種:
- Glisse 用於控制項:開關、滑桿、頁籤列和分段控制器,其拇指在拖動時會提升為透鏡。手動建構這類效果需要數天的工作。
- 此材質 用於表面:導覽列、膠囊導覽、面板、工作表、照片上的卡片,以及任何需要匹配現有設計系統或 Tailwind 主題的內容。
結合使用時的陷阱:
- 兩者都使用
lg-前綴。 Glisse 定義了.lg-glass、.lg-button、.lg-tab-bar以及變數--lg-blur、--lg-tint、--lg-rim和--lg-filter,這與此材質的標記衝突。在同時使用兩者的頁面上,請重新命名此材質的前綴(例如改為ylg-),或將 Glisse 範圍限定在一個重置這些變數的包裝器內。否則,兩者會默默地互相調整。 - Glisse 的深色模式是基於
data-theme="dark"或prefers-color-scheme,而不是 Tailwind 的.dark類別。在使用基於類別的深色模式時,請在<html>上同時設定data-theme和.dark,否則 Glisse 會保持淺色模式。 - Glisse 處理了
prefers-reduced-motion,但未處理prefers-reduced-transparency或prefers-contrast。 請在 Glisse 控制項周圍加入此技能無障礙章節中的降級方案。 - Glisse 的
.lg-glass已經使用內嵌的box-shadow繪製了一條邊緣。 不要在它之上再加入::before邊緣(規則 3:僅一條邊緣)。