主题与自定义
内置主题
在根元素(<html> 或任意容器)上设置 data-theme 切换三套内置主题:
data-theme | 说明 |
|---|---|
light(默认) | 浅色 |
dark | 深色 |
high-contrast | 高对比(WCAG AAA 友好,边框/文字对比更强) |
<html data-theme="dark">
…
</html>document.documentElement.dataset.theme = 'high-contrast'皮肤预设(可选)
@oas-ui/theme/skins.css 提供 6 套品牌色皮肤预设(violet / emerald / rose / amber / graphite / teal):在 data-theme 之上叠加 data-skin 即可切换,且与三套内置主题自由组合(皮肤只改品牌色相,不动尺寸/结构)。
<!-- opt-in:不引此文件则完全无影响 -->
<link rel="stylesheet" href="https://unpkg.com/@oas-ui/theme@2/skins.css" />
<html data-theme="dark" data-skin="violet">
…
</html>document.documentElement.dataset.skin = 'emerald' // violet | emerald | rose | amber | graphite | teal皮肤仅覆盖 --oas-color-primary,-hover / -active / -primary-text / 焦点环等派生档自动跟随;需要更深定制(表面色 / 圆角 / 密度)仍走下方 CSS 变量覆盖。
液态玻璃(glass.css)
@oas-ui/theme/glass.css 提供液态玻璃材质层(可选层,与 skins.css 同机制:opt-in 不引则零影响)——半透明 surface + backdrop 模糊 + 高光折光边 + 圆角放大 + 分层深影。在 data-theme / data-skin 之上叠加 data-glass 启用,三者自由组合:
<link rel="stylesheet" href="https://unpkg.com/@oas-ui/theme@2/glass.css" />
<html data-theme="dark" data-glass>
…
</html>机制:浮层 surface 组件(modal / drawer / popover / tooltip / dropdown / select 系面板 / message / snackbar / bottom-sheet / app-bar 等 25 个)统一消费 --oas-glass-blur(backdrop-filter 模糊档)与 --oas-glass-ring(折光描边环)两个变量;另有 9 个 controls/nav/notification 组件(button / switch / slider / app-bar / bottom-navigation / message / toast / snackbar / notification)消费 --oas-glass-refraction(边缘折射位移滤镜,内容面板不接;button 的禁用态与 app-bar 溢出弹层打开期间自动关闭)。不引 glass.css 时全部回落 none / transparent,组件行为与此前完全一致。
与 Apple 完整定义的关系(如实说明):本材质层是静态近似——达成半透明 / 高斯模糊 / 折光边 / 分层深影四项观感;标志性特征「边缘折射变形」已交付为静态置换近似(feDisplacementMap 边缘轮廓位移,仅边缘环带变形、中间恒不变形;data-URI 自包含滤镜,shadow DOM 内可解析);「动态流动感」(随交互变形、随环境变化的实时高光)由可选运行时 glass-fluid.js 提供(指针镜面高光 + 按压收紧,见液态玻璃)。引擎边界(如实):折射位移在 Chromium 系真实生效;Firefox 不执行 CSS filter 的 data-URI SVG 滤镜,安全无感降级为无折射(不破坏渲染)。
边界:
- 材质依赖背景反差——页面有色彩层次(渐变/图片)时质感最强,纯色同色相背景上减弱(文字仍走 token 安全档可读);
- 文字安全是硬约束:dark 档 surface 用低 alpha 高透(深色玻璃的材质感主场;alpha 档与文字档联动标定,感知对比度实测门禁 ≥60 分,见「液态玻璃画廊」);
- blur 只上容器级 surface(行级/长列表不接,避免大面积模糊的性能成本);
high-contrast主题下不启用(实心可访问性档优先);- 局部降级:任意容器覆盖
--oas-glass-blur: none; --oas-glass-ring: transparent; --oas-glass-refraction: ;(折射的停用值留空而非 none:button 的 hover/按下/选中态把 brightness() 与该变量组合书写,none与函数混排会使整条 filter 声明非法、亮度反馈失效;空值两条路径都合法)。密集列表场景建议对容器关掉折射,避免大量小滤镜栅格化开销;含浮层内容(dropdown/popover 等)的 app-bar 同样建议关掉(filter 会把向下溢出的子树裁进滤镜区域,内置溢出弹层已自动处理)。若宿主构建链会吞掉空值自定义属性(个别压缩器),可改用--oas-glass-refraction: saturate(1)(恒等滤镜,混排同样合法)作为停用值。
实时预览见液态玻璃画廊。
自定义主题(CSS 变量覆盖)
所有组件原则上只引用语义 token(见 docs/ui-spec.md §1,个别极值/预设除外),因此通过覆盖 CSS 变量即可定制品牌色,无需改组件:
:root {
/* 品牌色 */
--oas-color-primary: #7c3aed;
--oas-color-primary-hover: #8b5cf6;
--oas-color-primary-active: #6d28d9;
/* 文本 */
--oas-color-text-primary: #18181b;
--oas-color-text-secondary: #71717a;
/* 尺寸 */
--oas-radius-md: 8px;
--oas-control-height-md: 36px;
}Token 一览
| 组 | 变量 |
|---|---|
| 品牌 | --oas-color-primary(-hover/-active)、--oas-color-success、--oas-color-warning、--oas-color-danger |
| 文本 | --oas-color-text-primary/-secondary/-disabled |
| 边框/背景 | --oas-color-border、--oas-color-bg(-hover/-disabled)、--oas-color-overlay |
| 字号 | --oas-font-size-xs/sm/md/lg/xl |
| 间距 | --oas-space-1/1_5/2/2_5/3/4/4_5/5/6(4px 基准,含半步档) |
| 圆角 | --oas-radius-xs/sm/md/lg/xl |
| 控件 | --oas-control-height-xs/sm/md/lg/xl |
| 动效 | --oas-transition-fast/base、--oas-ease-out/in-out |
| 层级 | --oas-z-dropdown/sticky/fixed/overlay/modal/message/toast/tooltip |
| 焦点环 | --oas-focus-ring |
减弱动效
库内置 prefers-reduced-motion 支持,系统开启"减弱动效"后所有过渡/动画自动缩短。
自定义能力矩阵
主题 / 皮肤 / 布局 / 风格是四条正交、可自由组合的调节轴,「样式」是它们共同决定的结果:
| 轴 | 含义 | 机制 | 能到什么程度 |
|---|---|---|---|
| 主题 | 配色模式(明 / 暗 / 对比) | data-theme(light / dark / high-contrast) | 任意配色模式,可自定义 token |
| 皮肤 | 品牌色相(主色) | data-skin + skins.css(6 预设) | 任意主色,派生档自动跟随 |
| 布局 | 尺寸 / 间距 / 密度 / 圆角 / 容器 | --oas-space-* / radius-* / control-height-* / container-*;尺寸预设 | 任意密度 / 圆角 / 容器;RTL 自动镜像 |
| 风格 | 字形 / 动效 / 投影 / 焦点环 / 对比度 | --oas-font-size-* / transition / ease / shadow-* / focus-ring + -text 安全档 | 大部分设计语言可逼近 |
上限:凡能表达为 CSS 变量(token)的值都可纯 CSS 换肤、不改组件。 边界:① 组件级结构变体(size / variant / status / shape 等属性)属组件自身契约,不属全局轴;② 彻底换一套设计语言(字体栈 / 动效曲线族 / 对比度基准分级)已超出「默认一套 token」的表达范围,需由你在应用层自行定义设计系统(覆写 token 或自建主题层);③ 任意重绘组件内部结构 / DOM 刻意不做(保持组件一致性)。