13 KiB
Alright 参考站拆解
对标站点:https://alright.demo.nicetheme.xyz/ 拆解日期:2026-10-26 · 对照版本:
@stash/ui0.1.0 产物:DESIGN.md(规则)、COMPONENTS.md(契约)都按这份拆解更新。
1. 怎么拆的
不看截图猜,全部取实测值:
| 手段 | 用途 | 落盘位置 |
|---|---|---|
| 抓取主题 CSS(620KB,Autoptimize 合并包) | 读原始规则:令牌、:hover、@media、暗色覆盖 |
.ref/theme.css |
| Playwright 跑计算样式 | 拿到真实渲染值(字号、行高、圆角、阴影、尺寸、过渡) | .ref/probe.json |
| Playwright 截图 | 桌面 1440 / 移动 390、首页 / 详情页 | .ref/shots/*.png |
复现命令(都要先 npm run dev):
node .ref/probe.mjs # 重新采集计算样式 + 截图
node .ref/layout.mjs # 只量布局(列宽、头部高度)
.ref/ 只是拆解产物,不进构建、不进发布。
2. 站点底座(决定了哪些东西不该抄)
- WordPress + Bootstrap 5:按钮、表单、模态、分页的基础行为来自 Bootstrap;
- Alpine.js(
x-data/@click):交互状态,例如点赞、主题切换; - Swiper / Fancybox / Plyr / CKEditor:轮播、灯箱、播放器、编辑器,各有独立样式;
- 自建 iconfont(Project 4809463):线性图标,字号 18~24;
- 主题自己的工具类:
.text-lg、.flex-avatar、.item-badge、.box-block、.tags-list……
结论:只对齐主题层(令牌、尺寸、间距、圆角、阴影、交互节奏、组件外观), 不复刻 Bootstrap 的组件实现(下拉、模态那种带 JS 状态机的东西我们自己做,见 COMPONENTS.md §5)。
3. 设计令牌对照
| 参考站变量 | 值 | 我们的令牌 | 对齐情况 |
|---|---|---|---|
--gray-1 … --gray-8 |
#f7f8fa #f6f6f6 #eee #c9cdd4 #86909c #4e5969 #2c343c #1d2129 |
--su-gray-1 … -8 |
✅ 完全一致 |
--blue |
#3858f6 |
--su-color-primary |
✅ |
--red |
#ff3e3e |
--su-color-danger |
✅ |
--orange / --orange-dark / --orange-light |
#ffba3a / #ff8338 / #fffbe8 |
--su-color-warning / --su-color-orange-dark / --su-color-orange-light |
✅ 本轮补齐后两项 |
--green |
#4abd86 |
--su-color-success |
✅ |
--gradient-red |
linear-gradient(to right,#ff6034,#ff3e3e) |
--su-gradient-red |
✅ 本轮新增 |
.item-badge 置顶 / 付费 |
135deg #ff2f43→#ff6327 / #ff952f→#ff662b |
--su-gradient-hot / --su-gradient-paid |
✅ 本轮新增 |
| 认证角标 SVG | #FFB74A → #FD900F |
--su-gradient-verified |
✅ |
--border-radius-xs/sm/md/lg/max |
4 / 6 / 12 / 24 / 999 | --su-radius-* |
✅ |
--shadow |
0 6px 16px 0 rgb(27 26 49 / 1%) |
--su-shadow-card |
⚠️ 原为 2%,本轮改成 1% |
--shadow-2 |
rgb(27 26 49 / 3%) |
--su-shadow-hover |
⚠️ 原为 6%,本轮改成 3% |
--border-color / --border-light |
gray-2 / gray-3 |
--su-border / --su-border-strong |
✅ |
--card-border-color |
gray-1 |
--su-card-border |
✅ 本轮新增(卡片描边几乎不可见) |
--color-text / --color-secondary |
gray-7 |
--su-text-secondary |
✅ 本轮新增 |
--color-muted |
gray-6 |
--su-text-sub |
✅(我们的 text-muted 保留 gray-5 给更弱的占位) |
--bg-body / --card-bg |
gray-1 / #fff |
--su-bg-page / --su-bg-card |
✅ |
--bg-light |
gray-2 |
--su-bg-subtle(本轮改为 gray-1) |
⚠️ 参考站标签用的是 gray-1,见 §6 |
--animation-duration-fast/base |
.2s / .3s |
--su-duration-fast/base |
✅ |
--animation-timing-function-enter/leave |
ease-out / ease-in |
--su-ease-out / --su-ease-in |
✅ |
| 组件里的过渡 | 绝大多数是 all .3s ease-in-out |
--su-ease-in-out |
✅ 本轮新增,组件过渡改用它 |
4. 字号与行高(最容易抄错的一处)
参考站 :root 里的 --font-size-*(10/12/14/16/24)并不是页面实际字号,
真正生效的是 .text-* 工具类,且在小屏还有一组覆盖:
| 类 | 桌面 | 小屏(≤600px) | 典型用途 |
|---|---|---|---|
.text-xs |
13 / 20 | 12 / 16 | 标签、元信息 |
.text-sm |
14 / 22 | — | 正文(侧栏简介) |
.text-md |
16 / 24 | 15 / 24 | 正文、条目摘要 |
.text-lg |
18 / 26 | — | 条目标题、卡片标题 |
body |
16 / 24 | — | 全局 |
.item-badge 是 12 / 14.4(700 字重),标签 .tags-list a 是 13 / 20。
我们的处理:把 --su-font-size-* 改成 12 / 13 / 14 / 18 / 24,行高 16 / 20 / 22 / 26 / 32;
组件内文字只用到 sm 13(标签)、md 14(控件)、lg 18(图标),
xs 12 给角标。基础字号仍是 14(见 §10 的保留差异)。
5. 布局
| 项 | 参考站实测 | 说明 |
|---|---|---|
| 容器 | 1320 宽,居中,左右 60 | 对应 --layout-max-width 一类变量 |
| 三栏 | 左 330 / 中 660 / 右 330(gutter 24) | col-xl-3 / col-xl-6 / col-xl-3 |
| 顶栏 | 80 高,透明叠在渐变背景上 | 导航项 48 高、字号 16 |
| 内容起始 | y=112(顶栏 80 + 32) | 卡片与顶栏留 32 的呼吸 |
| 卡片内边距 | 40px 24px(侧栏 widget) / 12px(缩略图卡片) |
竖向留白明显大于横向 |
| 缩略图 | 3 列,间距 8,圆角 8 | 图集区块 |
这些是页面级参数,不进组件库;卡片的内边距档位(12 / 20 / 24)继续由 Card padding 管。
6. 组件实测(对齐依据)
| 组件 | 参考站选择器 | 实测关键值 | 我们的对应 |
|---|---|---|---|
| 卡片 | .box-block |
#fff、radius 12、1px solid gray-1、shadow 0 6px 16px 1%、padding 40/24、过渡 opacity/transform .3s |
Card |
| 缩略图卡 | .item |
#fff、radius 12、同款描边与阴影、padding 0(内容 12) |
Card padding="none" |
| 标签 | .tags-list li a |
高 24、13/20、radius 30、gray-1 底、gray-6 字、左侧 20×15 图标、hover 字色变 gray-8;hot 变体是 rgba(255,94,68,.1) 底 + 红字 |
Tag(soft / solid / icon / dot) |
| 状态角标 | .item-badge |
12/14.4、700、padding 2px 4px、radius 4、白字、红/橙渐变底 |
ItemBadge(本轮新增) |
| 数字角标 | .btn-icon small |
12px、padding 2px 5px、radius 10、红底白字 |
Badge(18 高) |
| 头像 | .flex-avatar + .avatar-badge |
96 / 40 / 20 三档;角标是 SVG 渐变对勾,尺寸 12 / 16 / 20 | Avatar(24/36/48 + 16/20 角标) |
| 图标按钮 | .btn-icon |
圆形,默认 42(变体 28 / 36 / 44),图标字号 16 / 20 / 24,无阴影 | IconButton(本轮改为圆形 28/36/44) |
| 按钮 | .btn / .btn-rounded |
radius 6 / 32、padding 8px 20px、字号 14、transition all .3s、primary:hover 是 opacity .8 |
Button(新增 shape="pill",hover 用 opacity) |
| 输入框 | .form-control |
高 36、radius 6、padding 8px 14px、1px solid gray-3、focus 换主色边框、无阴影 |
Input(描边改 gray-3,focus 主色) |
| 图片悬浮 | .custom-hover / .hover-content |
图片 scale(1.1) rotate(2deg);遮罩 rgba(0,0,0,.65) 淡入、图标上移 10px |
组合模式(见 COMPONENTS.md §4) |
| 分页 | .page-numbers |
32×32、radius 4、gray-2 底、当前项主色底白字 |
规划中(P3) |
| 弹层 | .nice-tips |
遮罩 rgba(0,0,0,.6)、内容 radius 12、padding 28、translateY(-40px)→0 .3s |
规划中(P3 Modal) |
| 滚动工具条 | .scroll-toolbar |
position:fixed; right:30; bottom:50%,内部是 42px 圆形按钮 |
ScrollTop |
7. 交互语言
| 行为 | 参考站做法 | 我们的做法 |
|---|---|---|
| 颜色 / 背景过渡 | all .3s ease-in-out(部分图标 color .3s) |
具体属性 + --su-duration-base + --su-ease-in-out |
| 主按钮 hover | opacity: .8(不改色) |
✅ 一致(primary / danger) |
| 次要按钮 hover | 换 gray-3 底 |
✅ 一致 |
| 图标按钮 hover | 轻微底色 + 文字加深,无阴影 | ✅ 一致 |
| 卡片 hover | 部分列表 translateY(-5px) scale(1.01);hoverable 只加深阴影 |
组件层只做阴影加深,位移留给页面(避免列表抖动) |
| 图片 hover | 图片放大 1.1 + 旋转 2°,遮罩淡入 | 组合模式,不做进组件 |
| 焦点 | 把 Bootstrap 的 box-shadow 去掉了(box-shadow:none) |
反着做:补 2px 主色 focus ring(a11y 要求) |
| 减少动效 | 用 @media (not (prefers-reduced-motion)) 包裹动画 |
✅ 每个带动效的组件都有 prefers-reduced-motion 分支 |
| 禁用 | 换浅底 + 弱文字(不是整体透明) | ✅ 一致(bg-subtle + text-muted) |
| 加载 | .btn.loading 浅底 + cursor: wait + pointer-events:none |
loading 自动 disabled + spinner + aria-busy |
8. 暗色方案(参考站已支持,我们留接口)
参考站用 body[data-scheme="dark|auto"] 覆盖整套变量,灰阶整体反相:
body[data-scheme=dark] {
--gray-1:#f7f8fa; --gray-2:#f2f3f5; --gray-3:#e5e6eb; --gray-4:#c9cdd4;
--gray-5:#494949; --gray-6:#303030; --gray-7:#202022; --gray-8:#0f0f11;
--color-text:var(--gray-1); --color-secondary:var(--gray-2);
--color-muted:var(--gray-4); --color-light:var(--gray-3);
--bg-body:var(--black); --bg-dark:var(--gray-8); --bg-secondary:var(--gray-7);
}
要点:语义变量跟着翻转,灰阶保持不变——所以组件只要引用语义令牌就自动适配。
我们的 --su-* 结构相同,后续加一份 [data-scheme='dark'] 覆盖即可;
仍有少量组件直接用了 --su-gray-*(Button secondary、Tag neutral、IconButton hover),
深色主题落地时要把这些改成 --su-bg-subtle / --su-bg-hover 之类的语义令牌。
9. 本轮对齐清单
令牌(tokens.css)
- 阴影 2%/6% → 1%/3%,补
0 … 0的位置参数; - 字阶 10/12/14/16 → 12/13/14/18,行高 16/20/22/26;
- 新增:
--su-color-orange-dark/light、--su-gradient-hot/paid/red、--su-text-secondary、--su-bg-subtle、--su-card-border、--su-ease-in-out、--su-focus-ring(-offset); - 控件高度:
sm 28→32;图标按钮24/32 → 28/36/44。
组件
| 组件 | 变更 |
|---|---|
Button |
新增 shape="pill";hover 改 opacity .8;禁用改浅底弱字;补 focus ring;补 reduced-motion |
IconButton |
改圆形,尺寸 xs/sm/md = 28/36/44,图标 16/20/24;补 focus ring |
Card |
描边改 --su-card-border(gray-1),阴影用新令牌 |
Tag |
重写:默认 neutral 浅底胶囊 24 高 13px;新增 variant="solid"、icon、dot;保留 shape="rounded" 做元信息前缀 |
Badge |
高度 16→18,字号 10→12 |
Input |
描边 gray-3;focus 主色边框 + 键盘 focus ring(:has(:focus-visible)) |
Avatar |
lg 认证角标 18→20,对齐参考站三档 |
ScrollTop |
过渡改 ease-in-out,补 focus ring |
ItemBadge |
新增:置顶 / 付费 / HOT / 草稿 状态角标 |
展示页:Buttons 补「形状」与图标按钮三档;Marks 重构为「浅底 / 实底 / 状态角标 / 数字角标 / 组合」;
组合示例的卡片标题加入 ItemBadge。
10. 保留的差异(有意为之)
| 差异 | 参考站 | 我们 | 原因 |
|---|---|---|---|
| 基础字号 | body 16/24 | 14/22 | 这是本地工具的控制台,不是阅读型博客;14 更紧凑。内容页(文章正文)建议用 16 |
| 卡片内边距 | 40px 24px |
12 / 20 / 24 档位 | 参考站的竖向留白是为 widget 设计的,工具里太松 |
| 标签图标 | 每个标签强制带 20×15 图标 | 可选 icon |
图标是主题的分类素材,通用组件不该强绑 |
| Bootstrap 组件 | 下拉、模态、分页都用 BS | 自己实现(规划中) | 不引 CSS 框架,避免 200KB+ 和样式覆盖战 |
| hover 位移 | 部分列表卡片抬升 5px | 组件不做位移 | 列表里位移会造成抖动;需要时页面自己加 |
| 动画时长 | 全站 all .3s |
按属性、默认 .3s | all 会把布局属性也带上,性能差 |
11. 生产标准补充(参考站没有的)
参考站是展示型主题,下面这些是我们作为组件库必须补的:
- focus-visible:所有可交互组件补 2px 主色焦点环(参考站把焦点样式删了);
- reduced-motion:
Button/IconButton/Card/Input/ScrollTop都有降级分支; - disabled 语义:
Button用真实disabled,loading同时aria-busy; - 图标按钮 label 必填:
IconButton.label是必填 prop,防呆; - 错误提示
role="alert"、Empty与Notice分工(§COMPONENTS); - 键盘可达:
ScrollTop隐藏时tabIndex=-1;Input 清除按钮是真实button; - 令牌约束:组件 CSS 里没有裸色值(
DESIGN.md§1 硬约束)。
12. 后续对齐项
暗色主题:已完成(data-scheme="dark|auto",见 DESIGN §7);- ScrollTop → 滚动工具条:参考站是「点赞 / 收藏 / 回到顶部」三键竖排,等有收藏功能再做;
- 图片悬浮遮罩:抽成组合模式(
Card hoverable+ 遮罩层),配合未来的Image组件; - 分页 / 弹层:按 COMPONENTS.md §5 的 P3 优先级补。