线上(box.shiroko.one/_/tamakyi)两个现象来自同一处:`--tb-navbar` 是实色,
顶栏那条带(y=20..80)把从右上角长出来的花枝齐刷刷切掉一段。
第一版顺手改成 transparent —— 花枝完整了,但顶栏"消失":导航失去依托,
文字直接压在花纹上。用户当场否掉,要求半透明。
- 顶栏:`rgba(253,246,248,0.72)` / 深色 `rgba(34,26,30,0.72)`,配
`.uk-navbar-container{backdrop-filter:blur(12px)}`(令牌只能是颜色,模糊写在规则里)。
0.72 有依据:导航文字 #6d555d 纯底 6.34:1,最坏情况(深花瓣在顶栏后面)压平后 5.08:1。
- 花枝 top -16px → 26px:顶栏半透明后,700~760px 宽度下枝头正好压在「登录」上(截图确认)。
- 手机底栏 #tb-mobile-utils 在 base.css 写死 rgba(255,255,255,.92),粉底上是一条白杠,
主题里改成同色系 0.92。
- 新增 TestNavbarNotFullyTransparent:拦 `transparent` / `rgba(...,0)` / `#rrggbb00`,
并说明"这不是审美偏好,是踩过之后立的规矩"。变异验证过(改回 transparent 立即 FAIL)。
约定同时写进 static/css/themes/_scaffold.css 的令牌说明。
- StaticVersion 20261022b → 20261022c:css 改了不提版本号,浏览器拿着旧样式,
现象就是"改了但线上没变"。
182 lines
11 KiB
CSS
182 lines
11 KiB
CSS
/* ============================================================================
|
||
主题底稿(scaffold)—— 复制本文件改名为 <slug>.css 即可新增一套主题。
|
||
不想手写 CSS 的话,用 dev/theme-builder/index.html 可视化生成(选图 / 拖位置 / 导出 zip)。
|
||
文件名即 slug:只允许小写字母、数字、连字符(如 sakura / ocean-mist)。
|
||
新增后需在 conf/app.ini 登记:
|
||
|
||
[theme]
|
||
default = default
|
||
available = default,sakura,ocean-mist
|
||
|
||
⚠️ 硬规则(违反会导致深色模式错乱或整页错位):
|
||
1. 两个块都必须写:浅色「html[data-theme-style="SLUG"]」
|
||
与深色「html[data-theme="dark"][data-theme-style="SLUG"]」。
|
||
只写浅色块会连深色模式一起覆盖(同特异性 + 本文件在 base.css 之后加载)。
|
||
2. 只改令牌(下方变量)与「组件微调」段。不要改布局:宽高、margin、padding、
|
||
display / flex / grid、position 一律不动 —— 主题不是换皮模板。
|
||
3. 本文件不参与构建,仅作参考;真正生效的是同目录下的 <slug>.css。
|
||
|
||
── 可用的 30 个令牌 ──────────────────────────────────────────────
|
||
底色层 --tb-bg 页面底色(html/body)
|
||
--tb-surface 卡片、输入框等前景面板
|
||
--tb-surface-2 次级面(标签底、进度条轨道、代码块)
|
||
--tb-surface-hover 悬停底(列表行、下拉项)
|
||
--tb-navbar 顶栏底色(不写则同 --tb-surface;
|
||
页面底色不是白时建议覆盖成 bg 或它的同色,否则顶栏会成为一条白带。
|
||
⚠️ 装饰层从页面角落长出来时,实色顶栏会把它齐刷刷切一段;
|
||
这时用半透明(如 rgba(...,.72))+ backdrop-filter: blur(),
|
||
但**不要写 transparent** —— 顶栏会失去依托,文字直接压在花纹上。
|
||
TestNavbarNotFullyTransparent 会拦住全透明。)
|
||
线条 --tb-border 边框、分隔线
|
||
文字 --tb-text 正文
|
||
--tb-text-secondary 次要文字(说明、meta、顶栏链接)
|
||
--tb-text-muted 弱化文字(占位、时间戳)
|
||
⚠️ 这三个都要满足 WCAG AA 的 4.5:1(对 --tb-bg 与压平后的 --tb-surface 都算)。
|
||
往浅调很容易掉到 3:1 以下(旧的 #8a919c 是 3.18:1),肉眼"淡一点"其实已经看不清了。
|
||
强调 --tb-primary 主色:链接、主按钮、进度条
|
||
--tb-primary-weak 主色 10% 左右的浅底(选中态、标签)
|
||
--tb-on-primary 主色作背景时的文字色(默认白字;深色块一般是深字)
|
||
主色同时是 14px 链接色,要 ≥4.5:1;但主色越深,
|
||
白字压在按钮上越清楚 —— 所以深色模式反而不该用白字。
|
||
形状 --tb-radius 卡片 12px / --tb-radius-sm 8px / --tb-radius-xs 6px
|
||
阴影 --tb-shadow 卡片默认 / --tb-shadow-hover 悬停
|
||
字体 --tb-font 字体栈(一般不改)
|
||
--tb-fs-xs 12px 标签、脚注、meta
|
||
--tb-fs-md 14px 正文、列表、按钮
|
||
--tb-fs-lg 16px 区块小标题、卡片标题
|
||
--tb-fs-xl 24px 页面标题、大数字
|
||
--tb-fs-hero 28px 首页主标题
|
||
这套阶梯 base.css 已统一定义,主题一般不要覆盖:
|
||
改一档会连带挤坏所有页面的排版,且与主题要解决的问题无关。
|
||
页面背景 --tb-page-image 整页背景图(cover,fixed)
|
||
--tb-page-pattern 整页图案(平铺,可叠加在背景图之上)
|
||
--tb-page-pattern-size 图案平铺尺寸(默认 auto)
|
||
--tb-page-position 背景焦点(cover 裁切时保留哪一侧,默认 center center)
|
||
装饰 --tb-deco 装饰图层,固定 10 个槽位(必须写满 10 个,缺的填 none);
|
||
适合放人物/摆件/光斑。默认 none。
|
||
值可以是图片,也可以是 linear-gradient / radial-gradient(纯"光")。
|
||
--tb-deco-size 对应每层的尺寸,如 auto 400px, 100% 100%, auto, …(10 个)
|
||
想随视口缩就用 clamp,不要写死 px:
|
||
人物/竖幅 auto clamp(min(calc(100vh - 24px), 231px), 46.67vh, 420px)
|
||
横幅/场景 clamp(min(calc(100vw - 24px), 587px), 70.57vw, 1067px) auto
|
||
内层 min() 是兜底:屏幕小到连下限都放不下时让位给视口。
|
||
background-size 的百分比是相对「容器 − 图片」,和 position 不同,
|
||
所以用 clamp 比用 % 好推理。
|
||
--tb-deco-position 对应每层的位置,如 calc(50% - 524px) calc(100% - 36px), …(10 个)
|
||
两值形式(水平 垂直);别用 left/bottom 关键字混搭成三值,
|
||
非法时整条声明作废,图层会静默掉回左上角。
|
||
|
||
── 素材规格(放 R2,不需要重新编译) ─────────────────────────────
|
||
页面背景图 2400×1600(3:2)或 2560×1440,WebP q80,≤300KB;明暗各一张:
|
||
https://r2.337845818.best/tamabox/themes/<slug>/bg-light.webp
|
||
https://r2.337845818.best/tamabox/themes/<slug>/bg-dark.webp
|
||
注意:背景图上还要叠卡片和文字,主题要保证「--tb-surface 不透明」
|
||
或足够对比;照片类背景建议配 10%~20% 的同色半透明遮罩。
|
||
平铺图案 200×200 或 400×400 可无缝平铺,PNG/WebP,≤40KB;
|
||
建议透明度 ≤15%,否则会和正文抢注意力。
|
||
设置页色块 由本文件浅色块的 --tb-bg 与 --tb-primary 自动生成,无需额外素材。
|
||
============================================================================ */
|
||
|
||
/* 1) 浅色(必须)—— 选择器里的 SLUG 换成文件名 */
|
||
html[data-theme-style="SLUG"] {
|
||
--tb-bg: #f7f8fa;
|
||
--tb-surface: #ffffff;
|
||
--tb-surface-2: #f4f6f8;
|
||
--tb-surface-hover: #f3f7ff;
|
||
--tb-navbar: var(--tb-surface); /* 顶栏底色,需要时改成 var(--tb-bg) 或半透明的同色 */
|
||
--tb-border: #e8eaee;
|
||
|
||
--tb-text: #1f2329;
|
||
--tb-text-secondary: #5c6370;
|
||
--tb-text-muted: #6b7280; /* AA 下限:白底 4.83:1。别再往浅调 */
|
||
|
||
--tb-primary: #0e6fd0; /* AA:白底 4.70:1。再浅就只够大号字了 */
|
||
--tb-primary-weak: rgba(14, 111, 208, 0.10);
|
||
--tb-on-primary: #ffffff;
|
||
|
||
--tb-radius: 12px;
|
||
--tb-radius-sm: 8px;
|
||
--tb-radius-xs: 6px;
|
||
|
||
--tb-shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 12px 28px -18px rgba(16, 24, 40, 0.20);
|
||
--tb-shadow-hover: 0 1px 2px rgba(16, 24, 40, 0.05), 0 18px 40px -20px rgba(16, 24, 40, 0.28);
|
||
|
||
--tb-font: system-ui, -apple-system, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif;
|
||
|
||
/* 整页背景:两者可同时用,图案叠在图片之上;不需要就保持 none */
|
||
--tb-page-image: none;
|
||
--tb-page-pattern: none;
|
||
--tb-page-pattern-size: auto;
|
||
--tb-page-position: center center; /* cover 裁切时保留哪一侧 */
|
||
|
||
/* 装饰层(放人物/摆件/光)。固定 10 个槽位,必须写满,缺的填 none——
|
||
值一多一少,多背景各列表就错位(会出现整页重复同一张图)。
|
||
尺寸用「auto <高度>」;位置统一写 calc:
|
||
calc(0% + 40px) 左对齐 + 40px
|
||
calc(50% + 0px) 居中
|
||
calc(100% - 36px) 右/下对齐 - 36px(百分比是相对「容器 − 图片」的剩余空间)
|
||
不要用 left / bottom 关键字混搭 —— 「水平居中 + 垂直贴底」会变成三值语法,
|
||
一旦写法不合规范整条声明作废,图层静默掉到左上角。 */
|
||
--tb-deco: none, none, none, none, none, none, none, none, none, none;
|
||
--tb-deco-size: auto, auto, auto, auto, auto, auto, auto, auto, auto, auto;
|
||
--tb-deco-position: left top, left top, left top, left top, left top,
|
||
left top, left top, left top, left top, left top;
|
||
}
|
||
|
||
/* 2) 深色(必须)—— 深浅两套必须成对,缺一段会让深色用户看到「浅色的深色主题」 */
|
||
html[data-theme="dark"][data-theme-style="SLUG"] {
|
||
--tb-bg: #1a1d23;
|
||
--tb-surface: #242830;
|
||
--tb-surface-2: #2d323c;
|
||
--tb-surface-hover: rgba(92, 141, 255, 0.12);
|
||
--tb-border: #3a404c;
|
||
|
||
--tb-text: #d8dce4;
|
||
--tb-text-secondary: #a8b0bd;
|
||
--tb-text-muted: #8b93a1;
|
||
|
||
--tb-primary: #5c8dff;
|
||
--tb-primary-weak: rgba(92, 141, 255, 0.14);
|
||
--tb-on-primary: #0b1016; /* 深色主色偏亮,白字只有 3.13:1 */
|
||
|
||
--tb-shadow: 0 1px 2px rgba(0, 0, 0, 0.30), 0 12px 28px -18px rgba(0, 0, 0, 0.55);
|
||
--tb-shadow-hover: 0 1px 2px rgba(0, 0, 0, 0.35), 0 18px 40px -20px rgba(0, 0, 0, 0.65);
|
||
|
||
--tb-page-image: none;
|
||
--tb-page-pattern: none;
|
||
--tb-page-pattern-size: auto;
|
||
--tb-page-position: center center; /* cover 裁切时保留哪一侧 */
|
||
}
|
||
|
||
/* 3) 按页面作用域覆盖(可选)
|
||
服务端会按请求路径给 <html> 打 data-page-scope,取值:
|
||
(无属性 = 全局)/ box(箱主页) / question(单题页) / admin(/user/questions)
|
||
/ profile(设置页等 /user/* ) / vote(投票页)
|
||
典型用法:「问题页正文长,人物退场;题目列表字更密,只留一点光」。
|
||
|
||
html[data-theme-style="SLUG"][data-page-scope="question"] {
|
||
--tb-page-image: none;
|
||
--tb-deco: none, none, none, none, none, none, none, none, none, none;
|
||
--tb-deco-size: auto, auto, auto, auto, auto, auto, auto, auto, auto, auto;
|
||
--tb-deco-position: left top, left top, left top, left top, left top,
|
||
left top, left top, left top, left top, left top;
|
||
}
|
||
|
||
⚠️ 覆盖块里同样要写满 10 个槽位。
|
||
⚠️ 深色要再写一条三重选择器,否则深色下会被浅色覆盖块污染:
|
||
html[data-theme="dark"][data-theme-style="SLUG"][data-page-scope="question"] { … }
|
||
⚠️ 没写覆盖块的页面自动沿用全局,不会出现「某页装饰消失」。
|
||
首页 / 与 /explore 不加载主题 css,配了也不会生效。 */
|
||
|
||
/* 4) 组件微调(可选,默认整段注释掉)
|
||
只允许「外观」层面的补充:边框、阴影、封面遮罩浓度等。
|
||
禁止改尺寸/间距/定位 —— 那属于布局,主题不管。 */
|
||
/*
|
||
html[data-theme-style="SLUG"] .uk-card-default {
|
||
border-color: transparent;
|
||
}
|
||
html[data-theme-style="SLUG"] .tb-pcard {
|
||
box-shadow: var(--tb-shadow);
|
||
}
|
||
*/
|