本文是 yutsukarin 博客当前视觉语言的设计基线。它以 Material Design 3 为骨架,并针对壁纸、长文阅读和 Web 平台加入实时毛玻璃扩展。后续新增页面和组件应优先复用这里定义的语义、token 与交互规则。
1. 设计目标
本站的视觉目标可以概括为四个词:柔和、清晰、真实、克制。
- 柔和:以淡粉动态主题为默认表达,避免高饱和色大面积争夺注意力。
- 清晰:颜色承担语义,层级依靠色调、模糊和空间关系建立,不依赖廉价的细线框。
- 真实:所有半透明表面都必须实时采样并模糊背后内容,不能只降低不透明度。
- 克制:阅读内容始终优先。文章正文不漂浮、不抬升,装饰和动效不能干扰长文阅读。
本站不是照搬 Material 组件库,而是使用 MD3 的设计 token、色彩角色、形状、层级和动效思想,构建适合 Astro 的 CSS 设计系统。
2. 核心原则
2.1 语义优先
组件不得直接依赖固定色值,而应使用语义角色:
- 主操作使用 primary 与 on-primary。
- 强调容器使用 primary-container 与 on-primary-container。
- 页面背景使用 surface。
- 卡片与导航使用不同等级的 surface-container。
- 正文使用 on-surface,次级说明使用 on-surface-variant。
- 分割线只在确有结构意义时使用 outline-variant。
颜色必须成对使用。例如 primary 上的文本或图标使用 on-primary,容器表面上的内容使用 on-surface 或 on-surface-variant。
2.2 色调层级优先于描边
MD3 主要通过容器色调表达层级。本站的卡片、顶栏、按钮和浮层默认采用 filled 或 elevated 语义,边框保持透明。只有输入框焦点、键盘焦点环、错误状态等功能性边界可以使用清晰描边。
2.3 壁纸与内容分离
壁纸负责情绪与空间,内容表面负责可读性。两者通过真实毛玻璃建立联系,但壁纸纹理不能破坏正文对比度。
2.4 阅读表面不是按钮
文章正文卡片是稳定的阅读平面:
- 悬停时不得上移、缩放或改变深度。
- 不能因鼠标经过而大幅改变亮度。
- 链接、按钮、目录项可以有局部状态反馈。
3. 色彩系统
默认主题色相为 345,即偏玫红的淡粉色。调色盘修改 —hue,其余颜色通过 OKLCH 和语义角色随之生成。
| 语义角色 | 本站用途 |
|---|---|
| —md-sys-color-primary | 当前状态、主操作、强调竖线、图标 |
| —md-sys-color-primary-container | 选中项、强调容器 |
| —md-sys-color-surface | 页面基础背景 |
| —md-sys-color-surface-container-low | 低层级容器 |
| —md-sys-color-surface-container | 普通卡片与导航 |
| —md-sys-color-surface-container-high | 浮层和高强调区域 |
| —md-sys-color-on-surface | 正文与主要标题 |
| —md-sys-color-on-surface-variant | 元数据与次级说明 |
| —md-sys-color-outline | 需要明确识别的功能边界 |
| —md-sys-color-outline-variant | 必要的弱分割线 |
浅色和深色主题共享同一语义结构。固定品牌色只用于不承载关键可读信息的装饰;文本与交互状态必须随主题变化。
4. 实时毛玻璃
毛玻璃是本站在 MD3 之外的重要视觉扩展。只设置半透明背景不算毛玻璃,合格表面必须同时具备:
background: var(--card-bg-transparent);backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate)) contrast(var(--glass-contrast));-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate)) contrast(var(--glass-contrast));4.1 模糊等级
| Token | 当前值 | 使用场景 |
|---|---|---|
| —glass-blur | 56px | 卡片、顶栏、设置面板、主浮层 |
| —glass-blur-soft | 40px | 按钮、次级浮层、媒体控件 |
| —glass-blur-subtle | 24px | 面板内部控件、轻量状态层 |
| —glass-saturate | 1.72 | 恢复模糊后的壁纸色彩 |
| —glass-contrast | 1.04 | 轻微增强背景分离 |
4.2 表面层级
- 主卡片使用 —card-bg。
- 壁纸覆盖与全屏模式使用 —card-bg-transparent。
- 设置面板等浮层使用 —float-panel-bg。
- 面板内部控件使用 —glass-control-light 或 —glass-control-dark。
- 嵌套玻璃同样需要 backdrop-filter,但应选择更轻的模糊等级。
浏览器不支持 backdrop-filter 时,使用更不透明的 tonal surface 降级,保证文字对比度;不得用整体 opacity 代替,因为它会同时削弱内容。
5. 形状系统
| Token | 数值 | 用途 |
|---|---|---|
| extra-small | 4px | 小提示、紧凑状态 |
| small | 8px | 菜单、输入控件、标签 |
| medium | 12px | 小卡片 |
| large | 16px | 普通浮动组件 |
| large-increased | 20px | 站点主卡片,即 —radius-large |
| extra-large | 28px | 对话框、侧边面板 |
| full | 9999px | 按钮、图标按钮、徽章 |
组件不得散落任意圆角。头像使用圆角矩形,保持柔和但不强制裁成圆形;按钮优先使用 full,信息卡片使用 medium 或 large-increased。
6. 字体与排版
| 内容 | 推荐角色 |
|---|---|
| 首页横幅标题 | Display Large,并响应式缩放 |
| 文章标题 | Headline Large |
| 卡片标题 | Title Medium |
| 正文 | Body Large |
| 卡片说明 | Body Medium |
| 按钮与标签 | Label Large |
| 元数据 | Label Medium 或 Body Small |
正文保持约 1rem / 1.5rem 的基准节奏,长文行宽控制在约 65–80 个字符。数学公式、代码块和表格可以横向滚动,但不得撑破正文容器。
标题前的短竖线属于标题组件,不属于其后的日期或图标。标题隐藏时,竖线也必须一起隐藏,不能因绝对定位漂移到下一行。
7. 间距与响应式布局
本站以 4px 为基础网格,以 8px 为主要节奏:
- 组件内部:4、8、12、16、24px。
- 组件之间:8、12、16、24px。
- 段落和章节:24、32、48px。
- 移动端页面边距:16px。
- 平板与桌面页面边距:24px。
| 等级 | 宽度 | 博客布局 |
|---|---|---|
| Compact | 小于 600px | 单栏文章流,辅助内容折叠或下移 |
| Medium | 600–839px | 主内容优先,可出现第二栏 |
| Expanded | 840–1199px | 主栏与辅助栏并置 |
| Large | 1200–1599px | 三栏结构,正文保持可读宽度 |
| Extra-large | 1600px 以上 | 继续约束正文,不无限拉宽 |
首页属于 Feed 布局;文章页属于 Supporting Pane 布局。右侧统计、日历和目录都是辅助信息,窄屏下不得挤压正文。
8. 组件规范
8.1 卡片
- 默认是 filled 或 elevated card,不使用装饰性一像素边框。
- 静止层级使用 —md-elevation-1;真正浮起的菜单和面板使用 —md-elevation-2。
- 普通内容卡片可在精确指针设备上轻微抬升。
- 文章正文卡片永远保持静止。
- 嵌套卡片通过 tonal surface 和间距区分,避免出现两层重复外壳。
8.2 按钮
- 主操作使用 primary filled。
- 次操作使用 tonal 或 text button。
- 图标按钮最小可交互区域为 48 × 48px。
- 按钮不使用装饰性细边框。
- hover 使用 8% 状态层,pressed 使用 12% 状态层。
8.3 顶栏
- 顶栏是高层级玻璃表面,必须实时模糊壁纸。
- 默认没有轮廓细线。
- 全屏或覆盖壁纸模式不能盖住顶栏。
- 品牌头像使用圆角,并与站点名保持稳定间距。
8.4 设置与调色盘
- 设置面板位于普通卡片、目录和右栏组件之上。
- 面板内部选项依靠填充与状态层区分,不使用大量矩形描边。
- 开启、关闭和快速反向操作必须平滑打断,并从当前视觉状态继续。
- 面板高度受视口限制,超出时内部滚动,不能延伸到页面底部之外。
8.5 日历与目录
- 日历分割线使用与当前背景形成足够对比的 outline-variant 或反相角色。
- 当月、当前日、文章日通过填充、文字权重和状态点建立层级。
- 目录只对当前章节使用高强调状态;其余项目保持低对比。
9. 层级与浮层
层级顺序从低到高为:
- 壁纸;
- 页面背景与装饰;
- 普通内容卡片;
- 顶栏与固定导航;
- 目录、搜索和普通浮层;
- 设置与调色盘;
- 对话框、遮罩与全局提示。
组件进入全屏、横幅或覆盖模式时,必须显式验证顶栏和设置面板的堆叠关系,不能依赖 DOM 顺序。
10. 动效
| Token | 当前值 | 用途 |
|---|---|---|
| —md-motion-duration-short | 180ms | hover、pressed、颜色变化 |
| —md-motion-duration-medium | 300ms | 面板、卡片和布局变化 |
| —md-motion-duration-long | 500ms | 大范围或强调过渡 |
| —md-motion-emphasized | cubic-bezier(0.2, 0, 0, 1) | 屏幕内状态变化 |
| —md-motion-decelerate | cubic-bezier(0.05, 0.7, 0.1, 1) | 元素进入 |
| —md-motion-accelerate | cubic-bezier(0.3, 0, 0.8, 0.15) | 元素退出 |
可中断动画优先使用 CSS transition、Web Animations API 或可反向状态机。禁止用延迟回调在动画结束后强制写死状态,因为快速点击会产生跳帧、重叠或两层残影。
当 prefers-reduced-motion: reduce 生效时,应取消位移、缩放和复杂过渡,只保留必要的即时状态反馈。
11. 可访问性
- 普通文本与背景至少达到 WCAG 4.5:1。
- 大号文本和关键 UI 边界至少达到 3:1。
- 所有交互支持键盘,并提供可见的 focus-visible。
- 图标按钮必须有可访问名称。
- 不能只用颜色表达选中、错误或当前状态。
- 毛玻璃必须在壁纸最复杂的区域测试对比度。
- 触控目标保持至少 48 × 48px。
12. 实现约束
必须
- 使用 —md-sys-* 和本站别名 token。
- 半透明表面同时声明标准与 -webkit- 的 backdrop-filter。
- 明暗主题共用语义角色。
- 在 600、840、1200、1600px 验证布局。
- 所有开合面板验证快速重复点击和反向操作。
- 新增固定或浮动组件时验证 z-index。
禁止
- 用 opacity 模拟毛玻璃。
- 给所有卡片和按钮统一加细边框。
- 在组件中大量硬编码颜色和圆角。
- 让文章正文产生悬停抬升动画。
- 让全屏内容覆盖顶栏。
- 用不可打断的定时器拼接面板动画。
- 为宽屏无限拉长正文行宽。
13. 发布前检查表
- 浅色、深色和不同主题色相下文字均清晰。
- 所有半透明卡片都能看到实时模糊后的壁纸变化。
- 卡片与按钮没有多余细线。
- 标题强调竖线没有漂移到元数据图标。
- 正文卡片悬停时保持静止。
- 调色盘可以快速开关并平滑打断动画。
- 设置面板没有被右栏或顶栏遮挡。
- 全屏与横幅模式不会覆盖顶栏。
- 移动端没有双层卡片或横向溢出。
- reduced motion 下没有非必要运动。
- 键盘焦点、触控目标和色彩对比符合要求。
14. 单一事实来源
- 设计 token:src/styles/variables.styl
- 全局卡片、按钮和阅读表面:src/styles/main.css
- 毛玻璃公共规则:src/styles/glass-surfaces.css
- 壁纸与顶栏:src/styles/wallpaper-navbar-transparent.css
- 可中断面板动画:src/styles/panel-animations.css
更新视觉系统时,应先修改 token 和公共规则,再处理组件特例。若文档与实现不一致,应在同一次改动中同步更新本文。
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时