Communitygithub.com

NotYousha/web-liquid-glass

在网页上构建 Apple 风格的液态玻璃表面(CSS + React/Next.js + Tailwind),使其呈现真正的玻璃质感而非模糊的盒子,并可选择手工制作的玻璃或 Glisse React 组件库。适用于在网站中添加玻璃、玻璃态、磨砂或半透明导航栏、胶囊导航、玻璃卡片、面板、芯片、分段控件或镜头按钮,调整玻璃效果以呈现 iOS 26/27 风格,或调试玻璃效果中的双边框、模糊嵌套等故障。

web-liquid-glass 是什么?

Web Liquid Glass 是一个面向生产环境的网页玻璃材质方案,提取自一个真实的 Next.js + Tailwind 网站。它提供了完整的 CSS 和 React 组件,用于创建超越简单模糊效果、具有真实玻璃视觉的界面元素。该材质包含四个核心部分:材质(模糊加饱和度提升)、边缘(光亮的发丝线)、光泽(顶部边缘内的柔和镜面高光)和深度(宽而非常柔和的低不透明度阴影),以及仅在 Chromium 中可用的折射效果。它支持 React/Next.js 和 Tailwind,并附有详细的浏览器兼容性说明(特别是 Safari 的限制)、性能优化规则(如避免嵌套 backdrop-filter 和动画继承属性)、辅助功能降级方案,以及与 Glisse 组件库的集成策略和潜在冲突解决方案。技能文档还提供了大量实战中总结的陷阱和解决方案,帮助开发者避免常见错误。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/NotYousha/claude-skills/tree/HEAD/skills/web-liquid-glass

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Web Liquid Glass

一个用于网站的生产级玻璃材质,提取自一个真实的 Next.js + Tailwind 网站。完整的可运行源代码位于 reference/ 目录中:

  • reference/liquid-glass.css:整个材质(令牌、表面、变体、形状玻璃、折射、降级)。约 2200 行,包含详细注释解释每个值。按需阅读所需章节,而非整个文件。
  • reference/glass.tsx:<Glass> React 组件和 SVG 折射滤镜。
  • reference/glass-specular.tsx:指针和倾斜跟踪的镜面高光。

参考代码引入了两个站点辅助函数(cn 和来自 lite-mode 模块的 LITE_CLASS)。请替换为项目自身的 cn/clsx 以及用于“关闭效果”的类名。名为 sky-*、kiosk-* 以及祈祷相关的选择器是特定于站点的变体示例。可删除它们,或将其用作模式参考。

什么是玻璃

玻璃由四个部分组成。如果网页版只实现了其中第一个,看起来就会很廉价:

  1. 材质:模糊且饱和度提升(约 200%)。低于约 150% 时会呈现为灰色塑料。增加亮度提升和对比度降低,使背后的繁忙内容扩散为柔和的洗涤效果。
  2. 边缘:光捕获边缘处的一条明亮发丝线,对侧边缘较暗。没有边缘的模糊永远不会看起来像玻璃。
  3. 光泽:顶部边缘内侧的柔和镜面高光。
  4. 深度:一个宽大、非常柔和、低不透明度的阴影,而非紧凑的卡片阴影。

折射(内容在边缘处弯曲)是第五个部分,也是唯一一个网页无法低成本完成的部分。它需要 backdrop-filter: url(#svg-filter),仅在 Chromium 中有效。

玻璃放置位置

玻璃应放置在导航层(导航栏、胶囊导航、浮动控件、面板)上,而不是正文内容上。玻璃上的文字对比度取决于其背后滚动的内容,因此无法保证。保持不透明卡片作为内容的默认样式,并让玻璃成为每个表面的可选项(.lg)。

耗费实际时间的规则

  1. 玻璃 CSS 必须与 @tailwind base 位于同一个文件中,并放在 @layer 内部。 Tailwind 按文件解析 @layer,因此单独的 CSS 文件会在 @layer base 上报错。去掉包装器会使规则成为非分层规则,而非分层规则会覆盖所有 Tailwind 工具类。。lg { position: relative } 会静默覆盖导航栏上的 fixed。
  2. 永远不要写 --x: calc(var(--x) * 0.7)。 这是一个循环:在计算值时无效,它会静默回退到继承的值而不报错。请使用第二个变量(--lg-clarity-bump、--lg-press)。
  3. 一个玻璃表面只有一个边缘,并且由 ::before 绘制。 两个边缘(一个 ::before 边缘加上内嵌 box-shadow 斜面,或边框盒外的扩展阴影)会产生“双边框”,任何 alpha 调整都无法修复。
  4. corner-shape 不会被继承。 当表面使用 corner-shape: squircle 时,每个在边界上绘制的伪元素都需要同时设置 border-radius: inherit 和 corner-shape: inherit,否则边缘会沿着与主体不同的曲线走。
  5. 不要对嵌套在玻璃内部的玻璃使用 backdrop-filter。 它会采样已经着色的背景,从而变得模糊不清。玻璃条内的选择芯片(.lg-chip)是一个没有自身模糊效果的着色透镜。
  6. 不要在 :root 上动画化继承的自定义属性。 它会使整个文档的样式失效:在包含 60 个表面的页面上,每帧约 11.6 毫秒,而直接为每个元素写入相同值只需 2 毫秒。
  7. 导航栏在每个滚动帧上都会重新模糊。 给 .lg-bar 一个较小的模糊半径并添加 contain: paint。如果设备仍然卡顿,设置 --lg-blur-bar: 0px;边缘和光泽承担了大部分视觉效果。
  8. 不要通过展平磨砂玻璃来修复故障。 一个近乎不透明的“纯色”导航栏会失去其外观。相反,应找到几何原因(遮蔽导致边缘处主体变薄,或重复的边缘)。
  9. 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),以便当内容在其下方滚动时,导航链接能保持文字对比度。

如何应用

  1. 将 reference/liquid-glass.css 中的令牌块和表面部分复制到项目的主 CSS 文件中,放在其现有的 @layer 块内部(规则 1)。
  2. 将颜色令牌映射到项目的调色板。参考代码使用了 shadcn 风格的 hsl(var(--card)) 令牌。
  3. 使用来自 reference/glass.tsx 的 <Glass> 组件,或直接使用 .lg、.lg-bar、.lg-nav、.lg-pane、.lg-chip 和 .lg-refract 类。
  4. 仅在其值得开销的地方添加来自 reference/glass-specular.tsx 的镜面高光(如主界面控件、主导航栏),并尊重 prefers-reduced-motion。
  5. 在 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 主题的内容。

组合使用时的陷阱:

  1. 两者都使用 lg- 前缀。 Glisse 定义了 .lg-glass、.lg-button、.lg-tab-bar 以及变量 --lg-blur、--lg-tint、--lg-rim 和 --lg-filter,这些与本材质的令牌冲突。在同时使用两者的页面上,请重命名本材质的前缀(例如改为 ylg-),或将 Glisse 限定在重置这些变量的包装器内。否则,两者会静默地相互调整。
  2. Glisse 的暗色模式基于 data-theme="dark" 或 prefers-color-scheme,而非 Tailwind 的 .dark 类。使用基于类的暗色模式时,请在 <html> 上同时设置 data-theme 和 .dark,否则 Glisse 会保持亮色。
  3. Glisse 处理 prefers-reduced-motion,但不处理 prefers-reduced-transparency 或 prefers-contrast。 请在 Glisse 控件周围添加本技能辅助功能章节中的降级方案。
  4. Glisse 的 .lg-glass 已经通过内嵌 box-shadow 绘制了一个边缘。 不要在其上添加 ::before 边缘(规则 3:只能有一个边缘)。

相关技能