材质

液态玻璃怎么写、挂在哪、做不出来时怎么退、在没显卡的机器上要付多少;小屋那边是暖墨阴影和水彩绿植。颜色层级在色彩页,这里讲写法、降级与代价。

工具 · 液态玻璃

玻璃.62/.78、三团光晕的色值见色彩页「中性底与玻璃」「背景光晕」。这一章的样例里真的挂了磨砂:只在样例滚到视口附近时挂,滚走就摘。

液态玻璃=半透明底+两档模糊+顶边亮线:侧栏30px·160%,卡片24px·150%

后面糊开、再提一点饱和度,上沿一道inset 0 1px 0的白线当受光的边。视口大小的面用重的一档,浮在内容上的小卡用轻的一档。

本站这里在用全站 · 侧栏导航

切着看同一张玻璃卡放在四种底上:光晕(浅)、光晕(深)、花底、没有光晕的平底。切强度、关亮线,看哪一项在哪种底上最显。卡上那行字是这张卡此刻的计算值。

光晕 · 浅
光晕 · 深
花底(像照片)
平底,没有光晕

读法:平底上玻璃几乎看不出来——磨砂得有东西可糊,光晕和玻璃是一套。花底上「不模糊」那档,后面的字和色块直接透上来。

代码

/* 视口大小的面:侧栏、顶栏、tab bar、手机底部面板 */
.side {
  background: var(--glass);                      /* 浅 rgba(255,255,255,.62) / 深 rgba(40,42,52,.55) */
  -webkit-backdrop-filter: blur(30px) saturate(160%);
  backdrop-filter: blur(30px) saturate(160%);
  border-right: 1px solid var(--glass-edge);     /* 侧栏的亮边 */
}
/* 浮在内容上的小卡、列表、对话框、提示条 */
.card {
  background: var(--glass);
  -webkit-backdrop-filter: blur(24px) saturate(150%);
  backdrop-filter: blur(24px) saturate(150%);
  border-radius: 18px;
  box-shadow: 0 10px 30px rgba(20,30,60,.08),
              inset 0 1px 0 var(--glass-edge);   /* 这一段就是顶边亮线 */
}
--glass-edge: rgba(255,255,255,.9);              /* 深色 rgba(255,255,255,.12) */

用在哪

plan:侧栏、tab bar、手机底部面板用重的一档(--blur-glass-strong),顶栏、详情对话框、菜单、提示条用轻的一档(--blur-glass)。会随正文长的面不在这里,见下面「磨砂放在哪」。本站:侧栏、顶栏、tab bar、「更多」面板都是30px·160%,条目卡不挂。

为什么

屋主要「参考苹果的UI和配色」;分层只靠玻璃、投影和分隔线,不用边框(反例在色彩页「中性底与玻璃」的对照里)。亮线放在阴影里,不占盒子、不改尺寸;浅色下.9的白很显,深色下只留.12。

坑

样张shua-glass.html是旧写法:侧栏、卡片是标准属性在前,玻璃按钮只写了backdrop-filter: blur(20px)、没配前缀。照着抄要按下面「前缀顺序」那条改过来。

出处:tools/plan/docs/design/SPEC-apple-glass.md:12「不用边框分层」、:3「屋主原话」;tools/plan/docs/design/shua-glass.html:36.side、:59.card、:11--shadow、:56.btn.glass;tools/plan/app/src/styles/tokens.css:356「--blur-glass」;tools/plan/app/src/App.css:39「--blur-glass-strong」(.sidebar)、:516「--blur-glass」(.topbar);tools/star/assets/star.css:392「blur(30px) saturate(160%)」(.side)

固定的渐变背景画在body::before上;底色只写html,body透明

光晕是position:fixed; z-index:-1的伪元素,不用background-attachment:fixed。html和body都写了背景时,body的底画在光晕上面,把它整个盖掉。

切着看左边是缩小的「页面」:外框当html、里面一层当body,body::before画三团光晕。把底色同时写到body上,光晕就没了。这是浏览器真的绘制顺序,不是换图。

  1. html的底画布,#F4F5F9
  2. body::before的光晕z-index:-1,排在画布之后
  3. body自己的底没写,透明——这一层什么都不画
  4. 正文与玻璃卡

代码

html { background: var(--bg); }                 /* 底色只写这里 */
body { /* 不写 background */ }
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(38vw 38vw at 12% 8%,   var(--blob1), transparent 60%),
    radial-gradient(34vw 34vw at 92% 18%,  var(--blob2), transparent 60%),
    radial-gradient(40vw 40vw at 70% 100%, var(--blob3), transparent 60%);
  filter: blur(10px);
}

用在哪

四个工具同一段;本站star.css第6节同样只给html写底。小屋走另一条路:暖雾直接写在body的背景上、background-attachment:fixed,规格写明这是「屋子不动,人在里面走」的观感来源。

为什么

只写body时,它的底会传给画布、画在最下面;html也写了,body的底就不再上交,画在body自己的盒子上——绘制顺序在z-index为负的伪元素之后,光晕被盖住。不用固定附着,是因为iOS Safari上它不生效,滚动时背景会跟着走。

坑

光晕被盖掉以后,离线算的对比度照样「成立」,脚本发现不了,只能看画面(刷刷2026-09-23验收时抓到的)。

出处:tools/shua/design-proposal.md:350「光晕不显示的坑」;tools/plan/app/src/styles/tokens.css:652「背景光晕」;tools/star/assets/star.css:259「底色只写在html上」;小屋Ysevan_web/docs/xiaowu-ui-spec.md「2.4 body 背景」(「屋子不动,人在里面走」)

backdrop-filter成对写:-webkit-在前、标准在后

Chrome只认标准那条,iOS Safari 18以前只认前缀那条,两条都要。顺序写反,过Vite 8(lightningcss)压缩会把标准那条并掉,Chrome上的玻璃就没了磨砂。

本站这里在用全站 · 侧栏导航

换着看左边是源码,中间是交出去的CSS,右边的玻璃块套的就是中间那份。选「过Vite 8压缩」再把顺序写反:产物里只剩前缀那条。压缩器那一步是照plan实测写的示意;玻璃块糊不糊是本浏览器的真结果。

源码顺序
怎么交付
源码
交出去的CSS
套上产物的玻璃块

—

—

代码

.glass {
  -webkit-backdrop-filter: blur(24px) saturate(150%);   /* 前缀在前 */
  backdrop-filter: blur(24px) saturate(150%);           /* 标准在后 */
}
/* 出货 CSS 里两条数量相等、成对出现 */

用在哪

只有plan过Vite 8构建,顺序在它那儿是真故障:源码18处,产物里标准属性只剩2处。刷刷、岗岗、card是静态页、不过压缩器,顺序不影响结果,四家还是统一前缀在前,省得哪天接了构建再踩一遍。本站star.css、kit.css全部前缀在前。

为什么

Chrome从来不认-webkit-backdrop-filter(上面那行本浏览器的回答就是),产物里只剩它,Chrome上就等于没写;build.cssTarget拦不住。

坑

dev预览不压缩,看着一切正常,只有构建产物里没磨砂。验收要打开产物读getComputedStyle(el).backdropFilter;数源码里字符串出现几次不算数,压缩会合并规则。

出处:tools/plan/docs/design/SPEC-apple-glass.md:116「-webkit-在前、标准在后」;tools/plan/app/src/App.css:2「构建陷阱」;memory/lightningcss-backdrop-filter-drop.md:14「Chrome从来不支持」、:19「How to apply」;tools/star/CLAUDE.md:33「-webkit-在前、标准在后」

降级探针连前缀一起测:@supports not ((A) or (B)),外层括号不能省

做不出磨砂时把玻璃提到.9不透明。只测标准写法,iOS Safari 18以前恒命中,手机上玻璃全成实心白块;少了外层括号,整条@supports语法不对、被丢掉,真做不出磨砂的浏览器又退不下来。

本站这里在用全站 · 侧栏导航

选着看三种探针写法×三类浏览器(示意)。右边的玻璃卡按选中的组合显示那台设备上会看到的样子。最下面那张表是本浏览器对这三条的真实回答。

探针写法
设备

—

本浏览器实测(A=backdrop-filter: blur(1px),B=-webkit-backdrop-filter: blur(1px))
写法条件成立?(成立=走兜底)这条@supports留下了吗
not ((A) or (B))——
not (A)——
not (A) or (B)——

代码

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root, [data-mode], [data-accent] {
    --glass:        var(--lt, rgba(255,255,255,.9))  var(--dk, rgba(40,42,52,.92));
    --glass-strong: var(--lt, rgba(255,255,255,.96)) var(--dk, rgba(44,46,58,.96));
  }
}
@media (prefers-reduced-transparency: reduce) { /* 同一套数 */ }

用在哪

四家现在都写对了(刷刷styles.css、岗岗三处、plantokens.css、cardtheme.css)。本站star.css第5节、kit.css与交互页的弹窗样式同一写法。

为什么

探针写错的两个方向代价不一样:测宽了,个别设备看到它撑不住的效果;测窄了,一整类设备永远看不到做好的东西,而且不报错、不留痕,只能靠人眼发现。not (A) or (B)是不合法的条件,整条规则直接被丢掉——表里第三行就是本浏览器丢掉它的样子。

坑

刷刷3.11.1在屋主手机上「从来没出过磨砂」就是窄探针(声明本身成对、都对)。改完别只看CSS.supports的返回值,要在旧Safari或真机上肉眼看一次。plan的构建产物一直是对的(压缩器会把探针补成两种写法),只有dev预览中招。

出处:tools/plan/docs/design/SPEC-apple-glass.md:110「降级探针必须同时测前缀形式」、:114「手机上玻璃全变成实心白块」;tools/gang/design-proposal.md:915「外层那对括号不能省」;memory/supports-probe-too-narrow.md:17「降级探针的错误方向是不对称的」、:21「四家最终账」;tools/plan/app/src/styles/tokens.css:680;tools/star/assets/star.css:312「降级」

磨砂只挂视口大小的面;随正文长的面用.78不磨砂,压在正文上的浮层用实色

侧栏、顶栏、tab bar、弹层的高度是常数,可以磨砂。条目卡、阅读栏、结算面板会随内容长到好几屏,挂磨砂会超出显卡纹理上限;联想浮层压在密排的正文上,半透明让两层字叠在一起。

本站这里在用全站 · 侧栏导航全站 · 搜索框

拖着看左边拖「面板有多长」,看它在屋主的设备上折成多少设备像素;挂着磨砂又超过16384,就是岗岗、刷刷踩过的整层丢弃。右边切浮层的两种做法,看压在字上读不读得清。

随内容变长的面板
设备
这块面板
016384设备像素(纹理上限)

—

压在正文上的联想浮层

示例正文:岗位手册里的密排段落,一行接一行,字压着字。联想浮层弹出来时正好盖在这几行上面,用户要一边读浮层里的候选,一边不被底下的字干扰。示例正文:再来一段同样密的字,好让浮层底下确实有东西。

  • 示例候选一 · 现金业务
  • 示例候选二 · 对公开户
  • 示例候选三 · 挂失补办

—

代码

/* 视口大小的面:可以磨砂 */
.side, .topbar, .tabbar, .sheet { background: var(--glass); -webkit-backdrop-filter: …; backdrop-filter: …; }
/* 随正文长的面:只靠不透明度 */
.entry, .reader, .panel.summary { background: var(--glass-strong); }     /* .78,深 .72 */
/* 压在正文上的浮层:实色 */
.suggest { background: var(--raised); box-shadow: var(--shadow-pop); }   /* 浅 #FFF / 深 #2C2D35 */
/* 刷刷的写法:强玻璃色压在页面底色上,同样不透明 */
.suggest { background: linear-gradient(var(--glass-strong), var(--glass-strong)), var(--bg); }

用在哪

岗岗的白名单只有五处:工作台头、目录栏(不是整列)、吸底条、≤900的目录抽屉、≤600的手机快捷栏与速查卡抽屉。刷刷3.14.0起结算面板改--glass-strong底,错题卡的模糊一并去掉。本站:条目卡不挂磨砂,搜索结果列表与复制气泡是实色。

为什么

岗岗2026-09-22真机实测:三栏各19,570px,超过纹理上限整层被丢,切配色后整栏空白、等下次滚动才出现;不超限也要每次滚动把整层重新光栅化。刷刷结算页模拟考60道错题时6.9–9屏高,手机上折合23661设备像素。浮层跟着打字频繁开合,挂磨砂等于把开销挪到最高频的那个动作上。

坑

以后新加会随内容变长的面板(列表、回顾、历史记录),先想它最长能有几屏。卡片里每张小卡各自再模糊一层,代价叠着算:刷刷结算页2040软件渲染滚动,原样66.7ms一帧,只去面板33.3ms,连错题卡一起去才16.7ms。

出处:tools/plan/docs/design/SPEC-apple-glass.md:123「磨砂只放在视口大小的表面」;tools/gang/design-proposal.md:899「磨砂只放在视口大小的表面上」、:910「实测三栏各19,570px」、:1397「为什么不加磨砂」;tools/shua/design-proposal.md:371「长面板不加」、:581「实底」

没显卡的机器上,瓶颈是模糊不是3D:玻璃底下有一处在变,整块模糊就每帧重算

软件合成时,玻璃后面任何一处重画都要把整块模糊重算一遍。半径不是关键,4px和24px一样掉帧;只留saturate、不模糊,才回到满帧。四个工具都还留着磨砂,关不关归屋主定;star自己做了降级档(下一条)。

本站这里在用全站 · 背景模糊

拖着看拖模糊半径;打开「玻璃底下有一块在变色」,右上的数是这台机器此刻的整页帧间隔(只在打开时量)——在屋主没显卡的台式机上打开,看到的就是那台的真代价。下面是各家在没显卡那档(2040×1019@1.25软件合成)量过的数,按半径对上。

这台机器此刻

没在量。打开「玻璃底下有一块在变色」才开始量。

没显卡那档(各家实测)

—

数值

各家实测:软件合成下模糊的代价
谁、什么情形挂着模糊去掉模糊
刷刷:3D关着,只让玻璃卡里一个24px方块每帧变色(有窗口的Chrome)约4帧/秒(放在不压玻璃的角落是120帧)去掉全站磨砂与光晕滤镜:页面100帧
刷刷:按压列表行,2040@1.25软件渲染帧间隔中位33.3ms(blur 4px也是33.3)只留saturate(150%):16.7ms
岗岗:来回滚动6秒,SwiftShader整页16–23拍/秒59–60拍/秒
岗岗:联想浮层的坏副本挂blur(30px),2040@1.25P95 33.4ms,长帧34–52个实色版P95 16.7ms,长帧0–1个
交互页「毛玻璃浮层」打开那1秒,合成器每帧2.9–3.3倍压暗不模糊1.3倍(基线1)
本页这块玻璃,底下每帧变色;本机无头Chrome软件合成(2040@1.25,CPU快的Mac)0–40px各档帧间隔中位16.7ms、长帧016.7ms、长帧0

有显卡的手机档(417×750@3.5走GPU)上,岗岗的浮层坏副本一个长帧都不多,交互页毛玻璃四种做法也分不出差别。本页那一行是反过来的提醒:快CPU扛得住这么小一块,代价只在慢机器上显形——判据先让它红过一次(每帧空转30ms时33.3ms、每秒长帧28个,判据是灵的),要看就在屋主那台上打开上面的「这台机器此刻」。

怎么量

相对判据:改动和基线跑同一串操作,交替跑3次合并,比整页requestAnimationFrame间隔的中位、P95,另数长帧(>25ms)的个数;要看合成器自己,另开tracing量每帧Display::DrawAndSwap。新加一块磨砂之前先做这个A/B。

为什么

CPU合成时,玻璃卡里任何一处重画都要重算整块模糊;砍3D画质(投影、张数、纸纹、分辨率)逐项都在噪声里。所以3D精简档只管少画、少出帧,不去碰界面层的磨砂。

坑

只看P95会漏掉稀疏卡顿:每次更新卡30ms的坏副本,卡帧不到总数5%,P95纹丝不动,必须另数长帧(让它红一次才发现)。无头Chrome每帧整屏重画,比有窗口时悲观,数字只当相对代价看;Windows的WARP未必和SwiftShader一样贵,屋主那台没实地量过。

出处:tools/shua/design-proposal.md:304「精简档为什么只砍这几样」、:396「软件渲染下是30帧」;tools/gang/design-proposal.md:920「软件渲染下磨砂的代价」、:1403「量过」;memory/glass-blur-cpu-compositing.md:13「Why」、:21「只看P95会漏掉稀疏卡顿」;交互页「毛玻璃浮层」的实测表;本页那一行是2026-10-08本机无头Chrome量的

背景模糊分三档:自动/开/关;自动靠WebGL探测有没有显卡,没测过先按「只压暗」

full:整页遮罩把背景糊到26px。lite:遮罩只压暗、弹层不模糊,侧栏这些常驻磨砂照旧。off:连常驻磨砂也关,玻璃提到近乎不透明。「自动」=WebGL带failIfMajorPerformanceCaveat拿得到上下文就full,拿不到(软件渲染)就lite。

本站这里在用全站 · 背景模糊全站 · 更多面板

点着看小窗是本站的缩样:左边侧栏常驻磨砂,「打开面板」弹出「更多」那样的整页遮罩。切档位看三档各做什么——只改这个小窗,不改全站设置。右边是这台机器上「自动」的真实判法。

示例正文:遮罩打开时,这几行字就是被糊开或被压暗的「背景」。

这台机器上
你的设置
—
此刻全站档位
—
显卡探测缓存
—
现测一次
还没测
「自动」怎么判
  1. 选了「开」→ full
  2. 选了「关」→ off
  3. 自动 · 测过、有显卡 → full
  4. 自动 · 测过、没显卡 → lite
  5. 自动 · 还没测过 → lite

代码

/* boot.js:样式表之前同步跑,首帧就是对的档位 */
function blurTier() {
  if (blurPref === "on") return "full";
  if (blurPref === "off") return "off";
  return gpu === true ? "full" : "lite";      // 没测过(null)也按 lite
}
/* star.js:load 之后空闲时测一次,连 UA 存进 star-gpu,UA 变了重测 */
var gl = canvas.getContext("webgl", { failIfMajorPerformanceCaveat: true });
ok = !!gl;                                    // 拿不到=软件渲染=没显卡
if (gl) { var lose = gl.getExtension("WEBGL_lose_context"); if (lose) lose.loseContext(); }

三档各做什么

  • full:整页遮罩背景从清楚糊到26px(开1s、关.3s),只糊不压暗;弹层面板.88玻璃+自己的磨砂。切主题的圆形揭开、强调色淡入、跨页过渡只在这一档做。
  • lite:遮罩不模糊、压暗淡入(浅rgba(20,24,36,.28)/深rgba(0,0,0,.5)),弹层面板不模糊、底提到.97;侧栏、顶栏、tab bar的常驻磨砂照旧。
  • off:同lite,并且常驻磨砂也关、玻璃提到近乎不透明,和「做不出磨砂」那套数一样。

为什么

代价不对等,往后果轻的那边错:误判成full,是没显卡那台整页卡;误判成lite,只是第一次打开少一点景深。所以没测过先按lite。过渡类只在full做,是因为View Transition要整屏截图,软件合成下最贵。降级的样子照交互页「毛玻璃浮层」的推荐:直接不模糊、压暗淡入、面板底提高,代价接近基线。

坑

无头Chrome测软件渲染,--use-gl=swiftshader要配--enable-unsafe-swiftshader才拿得到上下文;屋主的浏览器不会带旗标,带旗标那次的「能用」不能当结论。Windows还多一档WARP,macOS这边模拟不出来。圆环、刻度尺、照片抽屉三种弹层任何档位都只压暗。

出处:tools/star/assets/star.css:92「模糊档位」;tools/star/assets/boot.js:11「on → full;off → off;auto」;tools/star/assets/star.js:644「probeGpu」;tools/star/CLAUDE.md:92「自动模糊档」;memory/err-toward-lighter-consequence.md:10「代价不对等时,往后果轻的那边错」;memory/webgl-software-render-gate.md:12「测试陷阱」;交互页「毛玻璃浮层」「推荐」

玻璃风圆角阶:图标块9、品牌块10、按钮12、磁贴14、卡18、面板20、胶囊999;大屏上圆角跟着等比放大

以1440为基准等比放大时,圆角和别的尺寸一起乘缩放系数;不乘,卡变大了角显得硬。小屋另有4/6/8/12一套,只管小屋。

本站这里在用全站 · 品牌方块

拖着看拖「大屏缩放」从1到1.45(屋主台式2040宽是1.417),一组零件等比放大;打开「圆角不跟着乘」,看卡和面板的角在大屏上变硬。

图标块9px
品牌块10px
按钮12px
磁贴14px
卡18px
面板20px
胶囊999px

数值

--ui-scale: clamp(1, tan(atan2(100vw, 1440px)), 1.45);
--r-mark: calc(10px * var(--ui-scale));   /* 品牌块 */
--r-btn:  calc(12px * var(--ui-scale));   /* 按钮 */
--r-tile: calc(14px * var(--ui-scale));   /* 磁贴 */
--r-card: calc(18px * var(--ui-scale));   /* 卡 */
--r-pane: calc(20px * var(--ui-scale));   /* 面板、抽屉、弹层 */
--r-pill: 999px;                          /* 胶囊;图标块9 */

用在哪

plan的tokens.css就是这一套;岗岗的表C同一档(目录条目与输入框10、按钮12、中等面14、卡18、抽屉弹层20、胶囊999)。本站按钮12、品牌块10、图标块9、导航项10和这一套一致。star主窗口2026-10-08定:条目卡与页头22、样例框16保留——条目卡是整宽长卡,面积比工具里的卡大得多,圆角跟面积大一档;家族圆角阶管的是工具界面。

为什么

大屏等比放大时圆角同样乘缩放系数——不跟着放大,卡变大了角显得硬,构图就不等比了。数值来自样张:卡18、按钮12、品牌块10、图标块9。

坑

家族契约里的4 / 6 / 8 / 12圆角阶与暖墨阴影,2026-09-23起只约束小屋;工具端以液态玻璃规格为准,两套别混用。

出处:tools/plan/app/src/styles/tokens.css:280「圆角」;tools/plan/docs/ui-redesign-proposal-v2.md:350「圆角」;tools/plan/docs/design/SPEC-apple-glass.md:104「圆角同样乘--ui-scale」;tools/gang/design-proposal.md:700「表C:圆角与流式尺度」;Ysevan_web/docs/xiaowu-ui-spec.md「A.3 圆角、阴影、焦点环」(「只约束小屋本身」);tools/star/assets/star.css:188「--r-xs」;本站条目卡圆角:star主窗口2026-10-08定

小屋 · 暖纸

小屋没有磨砂。它的材质是纸:暖纸底、卡纸白、发丝线、暖墨阴影和水彩。色值见色彩页「暖纸色板」「暖墨阴影与发丝线」。

阴影是装裱的一部分:地毯上的卡浮起、墙上的画沉一倍;夜里发丝线和投影成对翻过来

白天一律暖墨rgba(74,77,53,…),不用纯黑。挂画的大投影放在伪元素上、跟着倾斜挪transform,不去动box-shadow。三根发丝线的分工见色彩页「暖墨阴影与发丝线」。

切着看墙上一张门厅卡(挂画投影),地毯上一只工具截图框(浮起)。切到「纯黑」看暖纸上的阴影发不发灰;切「夜里」看发丝线和投影一起翻;拖「倾斜」看大投影跟着挪,卡片自己贴边那层不动。

墙上:挂画投影0 16px 34px -14px暖墨.22
地毯上:浮起0 8px 20px -10px暖墨.11

代码

/* 挂画的大投影在 .set 的伪元素上:跟着倾斜挪 transform,模糊只画一次 */
.set::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  box-shadow: 0 16px 34px -14px rgba(74, 77, 53, 0.22);
  transform: translate3d(calc(var(--hall-tilt-x, 0) * -9px), calc(var(--hall-tilt-y, 0) * 5px), 0);
}
.card { border: 1px solid rgba(74, 77, 53, 0.17); box-shadow: 0 1px 2px rgba(74, 77, 53, 0.05); }  /* 贴地 */
.shotFrame { box-shadow: 0 8px 20px -10px rgba(74, 77, 53, 0.11); }                               /* 浮起 */

/* 夜里成对翻:卡纸变夜卡纸、墨色发丝线变浅色、投影换黑加深 */
.dark .card       { border-color: rgba(231, 225, 208, 0.11); background: #20232b; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); }
.dark .set::before { box-shadow: 0 16px 34px -14px rgba(0, 0, 0, 0.55); }
.dark .plate img  { box-shadow: 0 0 0 1px rgba(231, 225, 208, 0.08); }

为什么

纯黑阴影压在暖纸上会发灰。两档之外不要第三档,hover也不换档。工具卡摆在地毯上,门厅卡挂在墙上,投影要更沉。动box-shadow等于每帧重画一大片34px的模糊(小屋实测掉帧就掉在这),挪到独立伪元素上用transform移动,模糊只画一次,之后全在合成器上走。

坑

夜里那条选择器特异性更高,要在≥821px那个媒体查询段里再写一遍按卡片缩放的版本,否则夜里的投影冻在固定像素、不跟卡片缩放。色块与画纸各自不加投影,否则接缝处叠出一道脏影。

出处:Ysevan_web/app/hall.module.css「.set::before」(「挂画的大投影」)、「.card」(「动box-shadow本身等于每帧重画一大片模糊」)、「夜里的装裱」;Ysevan_web/app/projects/tools.module.css「.shotFrame」(「浮起档,暖墨色不用纯黑」);Ysevan_web/docs/xiaowu-ui-spec.md「A.3 圆角、阴影、焦点环」(「阴影用暖墨色」)、「4.6.2 数值」(「挂画投影在卡片上」「必须在同一个min-width: 821px段里再写一遍」)

水彩绿植=四层叠:水洗底、后层浅叶+冷影、前层中叶+二道水

一片叶子在<defs>里定义一次,<use>摆位;两层「重影」是同一组叶子换色、降透明度、偏几像素再画一遍。缺一层就成了扁平图标。

一层一层看门厅右上那枝垂柳,坐标原样搬来(只把取景框收到枝条那一块)。逐层开关;「只留前层」就是扁平图标的样子;切「夜里」看整体收一档亮度。

代码

<!-- ① 水洗底:一团极淡的绿雾,让枝叶像是从纸里洇出来的 -->
<ellipse cx="198" cy="146" rx="94" ry="150" fill="url(#dcWashHall)"/>
<!-- ② 后层:浅绿 + 一层偏移的海湾蓝冷影 -->
<g opacity=".6">
  <g fill="#A9BC96"><use href="#dcVineBack"/></g>
  <g fill="#6E8A93" opacity=".42" transform="translate(-7,5)"><use href="#dcVineBack"/></g>
</g>
<!-- ③ 前层:中绿 + 一层更深的「二道水」重影 -->
<g fill="#7E9367" opacity=".72"><use href="#dcVineFront"/></g>
<g fill="#4F5B3E" opacity=".17" transform="translate(2.5,3.5)"><use href="#dcVineFront"/></g>

/* 夜里:整体收一档,不逐叶改色 */
.dark .deco { filter: brightness(0.78) saturate(0.85); }

用在哪

小屋全站就这几处:门厅右上垂柳、门厅卡左下盆栽加一株四叶草,另有随笔页一枝小枝(工具页那枝随轨道改版删了)。完全不占布局、不接事件、没有动画——这是名片,不是花园。

为什么

冷影是「阴天里叶子的反光」,二道水是水彩第二遍上色的叠印感;四层叠出来才像水彩,缺一层就是扁平图标。叶片的位置、角度、大小是手调的,不抽象成「传参生成叶子」的组件——参数化只会变丑、更难改。

坑

SVG里的id要全局唯一:同一页有两处装饰时,撞了名<use>和fill="url(#…)"会引到别人的定义(本页就把id全换成了m开头)。宿主容器要position:relative; z-index:1,少写一个装饰就盖到字上。

出处:Ysevan_web/docs/xiaowu-ui-spec.md「9.4 SVG 内部结构(defs + use 复用)」(「四层叠出水彩的观感」「四处的id必须全局唯一」)、「9.5 实现形态」(「不抽象成传参生成叶子的通用组件」)、「9. 绿植装饰」、「9.1 八条硬约束」(「数量克制」)、「9.6 夜里」;Ysevan_web/app/page.tsx「VineDeco」

通用

起了view-transition-name的元素是backdrop root:它里面的磨砂只糊得到它自己

子元素的backdrop-filter够不着父元素后面的东西,看着像磨砂没了。父元素opacity小于1、带filter也一样。star的侧栏只在跨页过渡那一下起名,磨砂一直挂在侧栏自己身上。

本站这里在用全站 · 侧栏导航

切着看条纹底上一个空心父框,里面一枚磨砂小卡。给父框加不同的属性,小卡的磨砂都没了——这是本浏览器的真结果(Chrome 155实测)。小卡下面那行是它此刻的计算值:值一直没变。

—

代码

/* 只在跨页过渡那一下起名:boot.js 在 pagereveal、star.js 在 pageswap 时挂 html.vt-nav */
html.vt-nav .side   { view-transition-name: star-side; }
html.vt-nav .tabbar { view-transition-name: star-tabbar; }
/* 侧栏的磨砂挂在侧栏自己身上,不挪到伪元素或子元素上 */
.side { -webkit-backdrop-filter: blur(30px) saturate(160%); backdrop-filter: blur(30px) saturate(160%); }

用在哪

本站切页时侧栏、tab bar原地不动,靠的是临时起名;平时不起名。任何用View Transition的玻璃站都会碰到:起了名的元素里面别再放要糊后面的玻璃。

为什么

backdrop-filter只往上糊到最近的backdrop root为止。起了view-transition-name、opacity小于1、带filter、clip-path、mask的元素都会成为这一层的根(Chrome 155逐个实测过;transform、will-change不会)——里面的磨砂只糊得到这层根自己画的东西,根后面的页面够不着。

坑

计算值照样是blur(…):读getComputedStyle的量具看不出来,只能截图看。这一点是star第二阶段做跨页过渡时撞上的,所以侧栏的磨砂也别为了过渡方便挪到伪元素上。

出处:tools/star/CLAUDE.md:87「起了view-transition-name的元素是backdrop root」;tools/star/assets/star.css:118「backdrop root」、:921「html.vt-nav .side」;本页演示2026-10-08在Chrome 155无头实测