文章排版 .prose
文章正文由 markdown 管线输出,统一套用 .prose 样式;行内链接使用语义色链接,代码与公式分别走 Shiki 与原生 MathML。
中英文混排时,标题使用 tracking-tight;正文行高 1.75 左右,保证长文可读。
- 列表、引用、表格都映射到语义色 token。
- 不引入 webfont;不使用字距夸张的全大写小标题。
| 元素 | 规则 |
|---|---|
| 标题 | 字重 600,tracking-tight |
| 正文 | --foreground / --muted 两档 |
UI Standard · v1
颜色、字体、形状、动效、组件与交互的唯一事实来源。本页的每个色板、每个数值都直接读取生产globals.css的 CSS 变量,与线上页面同源 —— 改 CSS,本页自动跟随,不存在第二份手写数值。
Colour
两套语义色板共享同一组 token 名。左 :root、右 .dark,右侧面板读取的是 .dark 作用域声明,所以即使当前页面是亮色,也能看到暗色真值;文字色的 WCAG 比率按各自面板的 --background 计算。
Light 模式
:root
对比度对 --background
背景与表面
页面底色与三档表面:白卡只出现在 --surface 上,输入框与复制字段用 --surface-2,内嵌块用 --surface-3。
--background
页面底色
读取中…
--surface
卡片 / 面板底色
读取中…
--surface-2
输入框、复制字段
读取中…
--surface-3
内嵌块、骨架屏
读取中…
文字
正文与元信息的四级文字。比率对当前面板的 --background 计算;--faint 允许低于 AA,因为它只承载别处也有的元信息。
--foreground
正文 / 标题
读取中…
--muted
次要文字、excerpt
读取中…
--faint
日期、计数等元信息
读取中…
--accent
界面装饰文字(eyebrow、hover 标题)
读取中…
--secondary
次级强调文字
读取中…
--on-accent
主按钮上的文字
读取中…
主色与辅色
填充色与 pastel 装饰色。承载文字的主按钮使用 --accent-strong → --secondary-strong 渐变;pastel 只做渐变与描边,不承载正文。
--accent-strong
主按钮/链接 ink
读取中…
--accent-soft
主色淡底
读取中…
--accent-pastel
淡紫装饰
读取中…
--secondary-strong
辅色 ink
读取中…
--secondary-soft
辅色淡底
读取中…
--secondary-pastel
淡粉装饰
读取中…
--sky
第四色(仅渐变与光标光)
读取中…
--color-brand-lavender
历史来源色,不直接消费
读取中…
--color-brand-pink
历史来源色,不直接消费
读取中…
--color-brand-stone
历史来源色,不直接消费
读取中…
边框与投影
1px 内描边就是本站在静止态的“高度”。阴影一律由 --shadow-tint 着色,随主题变化。
--border
分隔线 / 卡片内描边
读取中…
--border-strong
hover 时的中性描边
读取中…
--shadow-tint
阴影着色
读取中…
--shadow-card
静止卡片:1px 内描边
读取中…
--shadow-card-hover
hover / 浮起
读取中…
--shadow-pop
弹层 / 模态
读取中…
渐变
填充渐变给装饰块,文字渐变只能用于大字号(--gradient-brand-text)。首页 hero 只用底色,没有叠加光晕。
--gradient-brand
品牌填充渐变(三色)
读取中…
--gradient-brand-text
标题文字渐变
读取中…
悬停系统(卡片 07 · 标签 C)
颜色以裸 RGB 三元组存储:一套色同时驱动卡片的外圈 / 内描边 / 柔光,以及标签的外圈。标签另用三个 alpha token 分开控制静止底色、外圈和描边。
--glow-sky
青 · 外圈扇形 / 柔光外晕
读取中…
--glow-lav
紫 · 外圈扇形 / 柔光核心
读取中…
--glow-pink
粉 · 外圈扇形
读取中…
--glow-ring-a
外圈透明度
读取中…
--glow-hairline-a
内描边透明度
读取中…
--glow-glow-a
柔光核心透明度
读取中…
--glow-glow-2-a
柔光外晕透明度
读取中…
--glow-shadow
hover 的双层外投影 + 内描边
读取中…
--card-lift
hover 时卡片底色混入比例
读取中…
--chip-wash-a
标签静止底色透明度
读取中…
--chip-ring-a
标签外圈透明度(1px 线要更高)
读取中…
--chip-hairline-a
标签静止描边透明度
读取中…
Dark 模式
.dark
对比度对 --background
背景与表面
页面底色与三档表面:白卡只出现在 --surface 上,输入框与复制字段用 --surface-2,内嵌块用 --surface-3。
--background
页面底色
读取中…
--surface
卡片 / 面板底色
读取中…
--surface-2
输入框、复制字段
读取中…
--surface-3
内嵌块、骨架屏
读取中…
文字
正文与元信息的四级文字。比率对当前面板的 --background 计算;--faint 允许低于 AA,因为它只承载别处也有的元信息。
--foreground
正文 / 标题
读取中…
--muted
次要文字、excerpt
读取中…
--faint
日期、计数等元信息
读取中…
--accent
界面装饰文字(eyebrow、hover 标题)
读取中…
--secondary
次级强调文字
读取中…
--on-accent
主按钮上的文字
读取中…
主色与辅色
填充色与 pastel 装饰色。承载文字的主按钮使用 --accent-strong → --secondary-strong 渐变;pastel 只做渐变与描边,不承载正文。
--accent-strong
主按钮/链接 ink
读取中…
--accent-soft
主色淡底
读取中…
--accent-pastel
淡紫装饰
读取中…
--secondary-strong
辅色 ink
读取中…
--secondary-soft
辅色淡底
读取中…
--secondary-pastel
淡粉装饰
读取中…
--sky
第四色(仅渐变与光标光)
读取中…
--color-brand-lavender
历史来源色,不直接消费
读取中…
--color-brand-pink
历史来源色,不直接消费
读取中…
--color-brand-stone
历史来源色,不直接消费
读取中…
边框与投影
1px 内描边就是本站在静止态的“高度”。阴影一律由 --shadow-tint 着色,随主题变化。
--border
分隔线 / 卡片内描边
读取中…
--border-strong
hover 时的中性描边
读取中…
--shadow-tint
阴影着色
读取中…
--shadow-card
静止卡片:1px 内描边
读取中…
--shadow-card-hover
hover / 浮起
读取中…
--shadow-pop
弹层 / 模态
读取中…
渐变
填充渐变给装饰块,文字渐变只能用于大字号(--gradient-brand-text)。首页 hero 只用底色,没有叠加光晕。
--gradient-brand
品牌填充渐变(三色)
读取中…
--gradient-brand-text
标题文字渐变
读取中…
悬停系统(卡片 07 · 标签 C)
颜色以裸 RGB 三元组存储:一套色同时驱动卡片的外圈 / 内描边 / 柔光,以及标签的外圈。标签另用三个 alpha token 分开控制静止底色、外圈和描边。
--glow-sky
青 · 外圈扇形 / 柔光外晕
读取中…
--glow-lav
紫 · 外圈扇形 / 柔光核心
读取中…
--glow-pink
粉 · 外圈扇形
读取中…
--glow-ring-a
外圈透明度
读取中…
--glow-hairline-a
内描边透明度
读取中…
--glow-glow-a
柔光核心透明度
读取中…
--glow-glow-2-a
柔光外晕透明度
读取中…
--glow-shadow
hover 的双层外投影 + 内描边
读取中…
--card-lift
hover 时卡片底色混入比例
读取中…
--chip-wash-a
标签静止底色透明度
读取中…
--chip-ring-a
标签外圈透明度(1px 线要更高)
读取中…
--chip-hairline-a
标签静止描边透明度
读取中…
规则:装饰色(pastel / sky / glow)不承载正文;正文链接使用 --accent(4.15:1,界面级放宽); 主按钮文字 --on-accent 落在 --accent-strong 上(5.35:1)。新增文字 token 必须在本页比率 ≥ 4.5:1。
Typography
8 级字号阶梯,全部来自文本工具类;下面的 px / 行高 / 字重由浏览器在渲染后实测。整站只使用系统字体栈,0 个 webfont 请求。
字号阶梯 · 8 级 / 4px 基线体系
字体栈首项:读取中…· 只使用系统字体,整站 0 个 webfont 请求
Display
首页大标题(仅一处)
设计系统 Design System 0123
读取中….text-display
H1
页面主标题
设计系统 Design System 0123
读取中….text-h1
H2
文章内二级标题
设计系统 Design System 0123
读取中….text-h2
Title
区块标题
设计系统 Design System 0123
读取中….text-title
Lead
导语 / 描述
设计系统 Design System 0123
读取中….text-lead
Base
正文
设计系统 Design System 0123
读取中….text-base
SM
卡片摘要、控件
设计系统 Design System 0123
读取中….text-sm
Caption
日期、标签、eyebrow
设计系统 Design System 0123
读取中….text-caption
文章正文由 markdown 管线输出,统一套用 .prose 样式;行内链接使用语义色链接,代码与公式分别走 Shiki 与原生 MathML。
中英文混排时,标题使用 tracking-tight;正文行高 1.75 左右,保证长文可读。
| 元素 | 规则 |
|---|---|
| 标题 | 字重 600,tracking-tight |
| 正文 | --foreground / --muted 两档 |
Shape
半径、容器宽度和阴影全部来自 token;右侧数值同样是浏览器计算后的结果。
三级圆角 + 全圆。控件用 control,卡片用 card,弹层用 panel。
--radius-control
按钮 / 输入框
读取中…
--radius-card
卡片
读取中…
--radius-panel
模态 / 大面板
读取中…
--radius-pill
药丸 / chip / 图标按钮
读取中…
页面最大宽度与三档内容宽度;--nav-height 是吸顶导航的实测高度。
--container-page
页面容器(.shell)
读取中…
--container-archive
归档页
读取中…
--container-read
阅读宽度
读取中…
--nav-height
吸顶导航高度
读取中…
阴影一律由 --shadow-tint 着色,随主题变化;卡片静止态只有 1px 内描边。
--shadow-card
静止卡片
读取中…
--shadow-card-hover
hover / 浮起
读取中…
--shadow-pop
弹层 / 模态
读取中…
Motion
没有动画库:入场、主题揭示、滚动进度和 hover 全部是 CSS。动效使用同一条 ease-out-expo 曲线与五个时长 token,系统开启“减少动态效果”时由全局媒体查询降级。
整站只有一条缓动曲线和五个时长;hover 时长在行内悬停时预览。
--ease-out-expo
唯一缓动曲线
读取中…
--duration-instant
即时反馈
读取中…
--duration-fast
hover / 颜色
读取中…
--duration-base
卡片 / 展开
读取中…
--duration-enter
入场动画
读取中…
--duration-slow
主题揭示
读取中…
两个动画皆为纯 CSS,无动画库;重播 = 重新挂载节点。
.reveal-rise
入场:上移 6px + 淡入
var(--duration-enter) 260ms · var(--ease-out-expo)
.toc-pill
主题切换
与右上角同一个组件:圆形 view-transition 揭示(0.618s),揭示期间冻结全站过渡, 并对吸顶玻璃头临时关闭 backdrop-filter。
页面级动效:route-transition(旧页 150ms 淡出 / 新页 260ms 淡入 + 6px 上移)。 滚动进度条与玻璃头的抬升阴影使用 animation-timeline: scroll(),不监听滚动事件。
Components
全部是 globals.css 里真实的组件类,直接在页面上跑 hover / focus / active 状态。
按钮
.btn-primary / .btn-ghost / .btn-icon;hover 位移 1px,active 缩放 0.98。
填充渐变使用两个 strong ink,保证两端都过 AA;不使用 pastel 作为文字底色。
输入框
.input;focus 时 accent 描边 + 22% 焦点环。
标签 chip(C 星屑)
.chip 静止 6% 三色 wash + 1px 淡紫描边;hover 时 1px 三色外圈旋转(5.5s)+ 两颗星点闪烁(1.7s),文字 → --accent-strong。
眉标与分组标签
.eyebrow(渐变短线 + 文字)与 .section-label(渐变竖条 + 文字)。
Section Eyebrow
分组标题
不做大写、不做宽字距:标签是中文字符,两者只会降低可读性。
链接与渐变文字
.link 正文链接;.text-gradient 仅用于大字号标题。
复制字段
.copy-field + useCopy():空闲 / 已复制 / 复制失败三态。
卡片(静止)
.card:1px 内描边就是全部高度;hover 效果在 06 节。
2026-11-04 · 约 6 分钟
一张卡片的解剖
元信息、标题、摘要与标签;整卡是一个链接(stretched link),标签浮在其上。
模态面板
.modal-panel + modal.js 打开:遮罩、Esc、焦点陷阱、滚动锁。
订阅更新
面板本身使用 94% surface + 16px 背景模糊;正文、按钮与链接沿用同一套 token。
玻璃吸顶导航
.glass-header:76% 背景 + 14px 模糊;滚动时抬升阴影由 scroll() 驱动。
全站搜索面板
.search-dialog-*;桌面面板 760px,移动端结果改 S2 三段式(标题 / 摘要 / 日期),日期独占整行且 nowrap。点导航栏放大镜或按 ⌘K/Ctrl+K 打开真实面板。
结果来自 /api/search(服务端 Fuse,索引不进浏览器);高亮用 mark 承载 accent 淡底,正文仍是 --muted。
微博时间轴
A 书脊:年份在卡片前,每个年份一条独立脊线;完整页年份吸顶,首页 compact 保持静态。卡片内只有 Oct. 4 这样的 month.day,没有年份和序号。卡片带文章同款 hover 光效,但文字/空白仍不可点击,只有图片打开灯箱。
年份是这条脊线的起点:它站在第一张卡片前面,而不是躲在卡片里。
下一年重新起一条线;年份在滚动中留在导航下方。
十年之约 · 虫洞
L1:友链页底部的 banner;复用 .card / card-interactive / card-spotlight,CTA 用 .btn-ghost。页脚另有同一 URL 的内联 .link(F1),不加新行、不加新颜色。
Ten years
随机去一位十年之约成员博客看看。每一次点击,都是一次真实的到访。
开源项目卡片
Portfolio(/about 正文之后);复用 .card + card-interactive + card-spotlight。全部卡片等宽两列,没有精选位,也没有额外的超链接按钮——整张卡就是仓库链接。
Interaction
卡片:1px 三色 conic 外圈随指针旋转、1px 内描边、跟随指针的柔光、上浮 2px。标签沿用同一套外圈语言,只是放慢成自转并加了两颗星点(见 05 的 chip 标本)。左右分别是 Light 与 .dark 作用域下的同一个组件。
Light 模式
rest
双描边柔光 · 07
外圈是 1px 三色 conic 渐变,从指针方向起算;内描边与柔光跟随指针位置,卡片只上浮 2px。
外圈顺序(自指针方向顺时针):青 → 紫 → 粉。静止时不绘制任何颜色。
Dark 作用域
rest
双描边柔光 · 07
外圈是 1px 三色 conic 渐变,从指针方向起算;内描边与柔光跟随指针位置,卡片只上浮 2px。
外圈顺序(自指针方向顺时针):青 → 紫 → 粉。静止时不绘制任何颜色。
结构与实现
<article className="card card-interactive card-spotlight relative flex flex-col p-5"> … </article>
实测(生产 CSS)
hover 只在 (hover: hover) and (pointer: fine) 下启用; 外圈颜色由 --glow-sky / --glow-lav / --glow-pink 三个 RGB 三元组驱动。
Rules
这些规则保证新页面落在同一套系统里;其中几条是历史 bug 的结论,不要“简化”掉。
必须
禁止
维护方式
src/app/globals.css —— 唯一的 token 与组件类来源(本页从它的 :root / .dark 规则里取值)。
src/lib/css-probe.js —— 运行时读取器:CSSOM 建立双主题作用域 + getComputedStyle 解析 var()。
src/components/ui-standard/*.js —— 各分区的预览组件;src/app/ui/page.js 是这一页。
新增 token 的三步:
本页故意不写死任何颜色或尺寸:只要 token 还在,预览就是对的;token 被删掉,对应行会显示“读取中…”, 这也是一次免费的回归检查。
页面路径 /ui · 与线上 CSS 同源 · 变更随 globals.css 自动生效。最后同步:悬停系统 07 上线时。