teaching-site-design-system
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTeaching Site Design System
教学网站设计系统
Token starter (copy this, don't re-derive):— fulltemplates/tokens.cssblock + dark theme + signature components (day-hero, glass-card, prompt-card, task-list, learning-goal, concept, unit, material, table). Paste into the:rootblock of<style>(vanilla SPA pattern) or use as externalindex.html.style.cssSchema authority: this skill defines visual tokens; data field names live in. When styling a component, read that file to know the data shape you're rendering._shared/domain-primitives.mdReference implementation:— the full production CSS this skill's tokens were extracted from.d:/GitHub/ai-workshop/index.html:11-1700
This skill defines the visual layer of a teaching site: color tokens, typography, geometry, components, dark mode strategy, and — critically — the reasoning behind each decision. The rationale matters more than the literal values; future sites can re-tune the values, but the why survives across projects.
Token起始模板(直接复制,无需重新编写):— 完整的templates/tokens.css代码块 + 暗黑主题 + 标志性组件(day-hero、glass-card、prompt-card、task-list、learning-goal、concept、unit、material、table)。粘贴到:root的index.html块中(原生SPA模式),或作为外部<style>使用。style.cssSchema权威来源:本Skill定义视觉Token;数据字段名称位于。在为组件设置样式时,请阅读该文件了解要渲染的数据结构。_shared/domain-primitives.md参考实现:— 本Skill的Token提取自该完整生产环境CSS。d:/GitHub/ai-workshop/index.html:11-1700
本Skill定义了教学网站的视觉层:颜色Token、排版、几何规范、组件、暗黑模式策略,以及至关重要的——每个决策背后的设计逻辑。设计逻辑比字面数值更重要;未来的网站可以调整数值,但设计的「初衷」会在不同项目中延续。
When to Invoke
何时调用
- Setting up a new teaching site (read tokens before writing first CSS).
- Adding a new visual element (badge, card, hero) — check whether an existing pattern covers it before inventing.
- Tuning dark mode (which token to override, which not to).
- Producing a corporate edition or ebook (same tokens flow to print CSS).
- Reviewing visual consistency complaints ("it looks inconsistent here").
- 搭建新教学网站时(编写第一行CSS前先读取Token)。
- 添加新视觉元素(徽章、卡片、Hero区域)时——先检查是否已有可用模式,再考虑创建新样式。
- 调整暗黑模式时(确定哪些Token需要覆盖,哪些不需要)。
- 制作企业版或电子书时(相同Token可应用于打印CSS)。
- 排查视觉一致性问题时(比如「这里看起来不一致」)。
The Foundational Decision: OKLCH, Not HEX/RGB
核心决策:使用OKLCH,而非HEX/RGB
css
:root {
--bg: oklch(99% 0.002 240);
--surface: oklch(100% 0 0);
--fg: oklch(18% 0.012 250);
--accent: oklch(58% 0.18 255);
--accent-2: oklch(66% 0.14 65);
}Why OKLCH (not or ):
#1a73e8hsl(...)- Perceptually uniform — and
oklch(60% ...)look like an equal step apart; HSL doesn't (its 60→70 yellow jumps visually huge but blue barely changes).oklch(70% ...) - Predictable dark mode — for each light token at , the dark equivalent is roughly
L=N%with the same chroma+hue. Mechanical.L=(100-N)% - works natively — e.g. soft accent tints (
color-mix(in oklab, ...)) compose cleanly, no manual rgba math.color-mix(in oklab, var(--accent) 18%, transparent) - Modern browser support is fine (Chrome 111+, Safari 15.4+, Firefox 113+). For a static teaching site this is acceptable.
If a stakeholder hands you brand colors as hex: convert once to OKLCH and never look back.
css
:root {
--bg: oklch(99% 0.002 240);
--surface: oklch(100% 0 0);
--fg: oklch(18% 0.012 250);
--accent: oklch(58% 0.18 255);
--accent-2: oklch(66% 0.14 65);
}为什么选择OKLCH(而非或):
#1a73e8hsl(...)- 感知均匀——和
oklch(60% ...)视觉上的亮度差距是均等的;而HSL做不到(比如60→70的黄色视觉变化极大,但蓝色几乎没变化)。oklch(70% ...) - 可预测的暗黑模式——对于亮度为的浅色Token,对应的深色Token亮度约为
L=N%,且色度和色相保持一致,实现起来非常机械简单。L=(100-N)% - 原生支持——例如柔和的强调色淡色(
color-mix(in oklab, ...))可以干净地组合,无需手动计算rgba值。color-mix(in oklab, var(--accent) 18%, transparent) - 现代浏览器支持良好(Chrome 111+、Safari 15.4+、Firefox 113+)。对于静态教学网站来说,这一支持范围完全可以接受。
如果利益相关方提供的品牌颜色是十六进制格式:只需转换一次为OKLCH格式,之后就无需再使用原格式。
Token Architecture (Two-Axis)
Token架构(双轴)
Axis 1: Semantic Surface Tokens
轴1:语义化表层Token
css
--bg /* page background */
--surface /* card / panel */
--surface-2 /* nested card / hover state */
--fg /* primary text */
--muted /* secondary text */
--muted-2 /* tertiary text / placeholder */
--border /* default border */
--border-strong /* emphasis border */These are structural — they describe role in the layout, not color. Dark mode swaps the values; component CSS doesn't change.
css
--bg /* 页面背景 */
--surface /* 卡片/面板 */
--surface-2 /* 嵌套卡片/悬停状态 */
--fg /* 主文本 */
--muted /* 次要文本 */
--muted-2 /* 三级文本/占位符 */
--border /* 默认边框 */
--border-strong /* 强调边框 */这些是结构性的——它们描述的是在布局中的角色,而非具体颜色。暗黑模式会替换这些Token的值,但组件的CSS无需修改。
Axis 2: Accent Tokens (Dual Accent Strategy)
轴2:强调色Token(双强调色策略)
css
--accent /* primary action color — blue/violet typically */
--accent-soft /* faint tint, for hover backgrounds, badges */
--accent-deep /* high-contrast variant, for hover text */
--accent-2 /* secondary accent — orange/amber typically */
--accent-2-soft
--accent-2-deepWhy two accents (not one + grayscale): teaching sites have two equally important attention paths:
- Action path (): "click me", "copy this", "navigate here" — typically cool color (blue).
--accent - Content path (): "look here, this is rich content" — Day hero numerals, PROMPT badges, callout backgrounds. Typically warm color (orange/amber).
--accent-2
Single-accent designs end up using grayscale for content emphasis, which makes everything feel like a button. Dual-accent separates "things you click" from "things you read carefully".
css
--accent /* 主要操作色——通常为蓝色/紫色 */
--accent-soft /* 淡色变体,用于悬停背景、徽章 */
--accent-deep /* 高对比度变体,用于悬停文本 */
--accent-2 /* 次要强调色——通常为橙色/琥珀色 */
--accent-2-soft
--accent-2-deep为什么使用双强调色(而非单一强调色+灰度):教学网站有两条同等重要的注意力路径:
- 操作路径():「点击我」「复制这个」「导航到这里」——通常为冷色调(蓝色)。
--accent - 内容路径():「看这里,这是重要内容」——Day Hero数字、PROMPT徽章、提示框背景。通常为暖色调(橙色/琥珀色)。
--accent-2
单一强调色的设计最终会用灰度来强调内容,这会让所有元素看起来都像按钮。双强调色可以区分「可点击的元素」和「需要仔细阅读的内容」。
Status Tokens
状态Token
css
--success, --success-soft /* learning goals ✓, copy success */
--warning, --warning-soft /* gotchas, optional warnings */
--danger, --danger-soft /* errors, destructive actions */Always provide a variant for backgrounds; the base is for text/icons.
-softcss
--success, --success-soft /* 学习目标✓、复制成功 */
--warning, --warning-soft /* 注意事项、可选警告 */
--danger, --danger-soft /* 错误、破坏性操作 */始终为每个状态颜色提供变体作为背景色;基础色用于文本/图标。
-softTypography: One Font Stack to Rule Them All
排版:一套字体栈统一所有场景
css
--font-display: "Nunito", "jf-openhuninn-1.1", "jf-openhuninn",
"Gen Jyuu Gothic", "Taipei Sans TC Beta",
"PingFang TC", "Noto Sans TC",
system-ui, sans-serif;
/* All four roles point to the same stack */
--font-body: var(--font-display);
--font-serif: var(--font-display);
--font-mono: var(--font-display);Why one stack for everything on a Chinese-language teaching site:
- Latin + 中文 混排在 90%+ 的段落都會出現。每換一種字體就會出現「字體斷裂感」。
- The fallback chain handles bilingual rendering — Nunito for Latin glyphs, openhuninn for 中文.
- Mono / serif variants are mostly used for spacing / weight effects, not actually different typefaces. Implement via ,
font-feature-settings,letter-spacinginstead of swapping fonts.font-weight
Exception: ebook PDF for formal print may use a true serif (Source Han Serif) — that's the only place to break this rule.
css
--font-display: "Nunito", "jf-openhuninn-1.1", "jf-openhuninn",
"Gen Jyuu Gothic", "Taipei Sans TC Beta",
"PingFang TC", "Noto Sans TC",
system-ui, sans-serif;
/* 四个角色都指向同一字体栈 */
--font-body: var(--font-display);
--font-serif: var(--font-display);
--font-mono: var(--font-display);为什么中文教学网站要使用同一字体栈覆盖所有场景:
- 90%以上的段落都会出现拉丁文字+中文混排。每更换一种字体就会出现「字体断裂感」。
- 回退链可处理双语渲染——Nunito用于拉丁字符,openhuninn用于中文。
- 等宽/衬线变体主要用于间距/字重效果,而非实际使用不同字体。可通过、
font-feature-settings、letter-spacing实现,无需切换字体。font-weight
例外情况:正式印刷的电子书PDF可使用真正的衬线字体(Source Han Serif)——这是唯一可以打破此规则的场景。
Geometry Tokens
几何Token
css
--r-sm: 6px; /* buttons, small chips */
--r-md: 10px; /* cards, panels */
--r-lg: 14px; /* heroes, large containers */
--sidebar-w: 268px;
--header-h: 56px;
--content-max: 880px; /* reading line length cap */
--shadow-lift:
0 6px 18px -10px oklch(20% 0.02 250 / 0.18),
0 2px 4px -2px oklch(20% 0.02 250 / 0.06);Three radii is enough — more produces visual chaos. Match radius to element scale: button → sm, card → md, hero → lg.
--content-max: 880pxDouble-layered shadows (): one wide-soft + one tight-tighter. Single-layer shadows look digital; double-layer mimics physical card lift. Always negate the y-offset (, ) so the shadow doesn't bleed below the element.
--shadow-lift-10px-2pxcss
--r-sm: 6px; /* 按钮、小标签 */
--r-md: 10px; /* 卡片、面板 */
--r-lg: 14px; /* Hero区域、大型容器 */
--sidebar-w: 268px;
--header-h: 56px;
--content-max: 880px; /* 阅读行长度上限 */
--shadow-lift:
0 6px 18px -10px oklch(20% 0.02 250 / 0.18),
0 2px 4px -2px oklch(20% 0.02 250 / 0.06);三个圆角值足够——过多的圆角会导致视觉混乱。圆角值要与元素尺寸匹配:按钮→sm,卡片→md,Hero区域→lg。
****是经过深思熟虑的——舒适的阅读行长度约为60–75个CJK字符。太宽会像文档,太窄会像桌面端强制使用移动端布局。
--content-max: 880px双层阴影():一层宽而柔和 + 一层紧凑。单层阴影看起来很数字化;双层阴影模拟实体卡片的悬浮感。始终将y偏移设为负值(、),这样阴影不会溢出到元素下方。
--shadow-lift-10px-2pxSignature Components
标志性组件
1. Day Hero Numeral
1. Day Hero数字
css
.day-hero-numeral {
font-family: var(--font-serif);
font-size: clamp(120px, 16vw, 200px);
font-weight: 500;
line-height: 0.85;
letter-spacing: -0.05em;
color: var(--accent-2);
text-shadow: 0 1px 0 color-mix(in oklab, var(--accent-2) 18%, transparent);
}
.day-hero:hover .day-hero-numeral {
color: var(--accent-deep);
text-shadow:
0 2px 0 color-mix(in oklab, var(--accent-2) 22%, transparent),
0 18px 40px color-mix(in oklab, var(--accent) 22%, transparent);
}Why a giant numeral instead of decorative SVG / illustration for Day headers: an abstract SVG looks like a placeholder ("they forgot to put a real image"). A 200px "D2" reads as intentional, confident, navigational. Specific > abstract.
Why : scales with viewport width but with floor and ceiling so it never feels broken on mobile (would be 120px) or absurd on 4K (capped at 200px).
clamp(120px, 16vw, 200px)Why fade-in, not : if fails to fire (e.g. CSS is in play, see ), the numeral stays at forever. With , the default state is visible; animation only "plays once if triggered".
@keyframesopacity: 0 → transitionIntersectionObserverzoomstatic-spa-interactionsopacity: 0@keyframescss
.day-hero-numeral {
font-family: var(--font-serif);
font-size: clamp(120px, 16vw, 200px);
font-weight: 500;
line-height: 0.85;
letter-spacing: -0.05em;
color: var(--accent-2);
text-shadow: 0 1px 0 color-mix(in oklab, var(--accent-2) 18%, transparent);
}
.day-hero:hover .day-hero-numeral {
color: var(--accent-deep);
text-shadow:
0 2px 0 color-mix(in oklab, var(--accent-2) 22%, transparent),
0 18px 40px color-mix(in oklab, var(--accent) 22%, transparent);
}为什么用巨大的数字而非装饰性SVG/插图作为Day标题:抽象SVG看起来像占位符(「他们忘了放真实图片」)。200px的「D2」会被解读为有意图、自信、具有导航性。具体>抽象。
为什么使用:随视窗宽度缩放,但有下限和上限,因此在移动端不会显得过小(最低120px),在4K屏幕上也不会显得夸张(最高200px)。
clamp(120px, 16vw, 200px)为什么使用淡入,而非:如果触发失败(比如开启了CSS ,详见),数字会一直保持。使用时,默认状态是可见的;动画仅在触发时「播放一次」。
@keyframesopacity: 0 → transitionIntersectionObserverzoomstatic-spa-interactionsopacity: 0@keyframes2. PROMPT Block (Orange Badge + Dark Code)
2. PROMPT区块(橙色徽章+深色代码区)
css
.prompt-block {
background: oklch(15% 0.02 250); /* always dark, even in light mode */
color: oklch(92% 0.005 250);
border-left: 4px solid var(--accent-2);
padding: 14px 16px;
border-radius: var(--r-md);
}
.prompt-block::before {
content: 'PROMPT';
display: inline-block;
background: var(--accent-2);
color: white;
padding: 2px 10px;
border-radius: 999px;
font-size: 11px;
font-family: var(--font-mono);
letter-spacing: 0.1em;
margin-bottom: 8px;
}Why orange () for PROMPT: blue () is reserved for "clickable / navigation". Orange marks "this is a recipe — read carefully and copy verbatim". Three months in, learners associate orange = prompt block automatically.
--accent-2--accentWhy dark background even in light mode: code-y content reads as code-y. Switching light/dark would feel like the prompt is "less serious" in light mode.
css
.prompt-block {
background: oklch(15% 0.02 250); /* 始终为深色,即使在浅色模式下 */
color: oklch(92% 0.005 250);
border-left: 4px solid var(--accent-2);
padding: 14px 16px;
border-radius: var(--r-md);
}
.prompt-block::before {
content: 'PROMPT';
display: inline-block;
background: var(--accent-2);
color: white;
padding: 2px 10px;
border-radius: 999px;
font-size: 11px;
font-family: var(--font-mono);
letter-spacing: 0.1em;
margin-bottom: 8px;
}为什么PROMPT使用橙色():蓝色()被保留用于「可点击/导航」元素。橙色标记「这是操作指南——请仔细阅读并原样复制」。三个月后,学习者会自动将橙色与PROMPT区块关联。
--accent-2--accent为什么浅色模式下也使用深色背景:代码类内容看起来就应该像代码。切换明暗模式会让PROMPT在浅色模式下显得「不够正式」。
3. Glass Card (glass-card
)
glass-card3. 玻璃卡片(glass-card
)
glass-cardcss
.glass-card {
background: color-mix(in oklab, var(--surface) 60%, transparent);
backdrop-filter: blur(12px) saturate(140%);
border: 1px solid color-mix(in oklab, var(--border) 80%, transparent);
border-radius: var(--r-md);
padding: 16px 20px;
box-shadow: var(--shadow-lift);
}Why translucent + backdrop-filter: on a page with rich background (gradient, dotted pattern, illustrations), opaque cards feel heavy. Glass cards let content breathe, signal "this floats on top of the document".
Caveat: requires browser support. Safari needs prefix. On unsupported browsers, the fallback is just the 60%-opacity color — degrades gracefully.
backdrop-filter-webkit-backdrop-filtercss
.glass-card {
background: color-mix(in oklab, var(--surface) 60%, transparent);
backdrop-filter: blur(12px) saturate(140%);
border: 1px solid color-mix(in oklab, var(--border) 80%, transparent);
border-radius: var(--r-md);
padding: 16px 20px;
box-shadow: var(--shadow-lift);
}为什么使用半透明+背景模糊:在有丰富背景(渐变、点状图案、插图)的页面上,不透明卡片会显得厚重。玻璃卡片让内容更透气,传递出「漂浮在文档上方」的信号。
注意事项:需要浏览器支持。Safari需要添加前缀。在不支持的浏览器上,回退方案是仅显示60%透明度的颜色——降级效果优雅。
backdrop-filter-webkit-backdrop-filter4. Task Checkbox (Three-State Visual)
4. 任务复选框(三态视觉)
css
.task-checkbox {
width: 18px; height: 18px;
border: 1.5px solid var(--border-strong);
border-radius: var(--r-sm);
display: grid; place-items: center;
transition: all 120ms ease;
}
.task-item:hover .task-checkbox { border-color: var(--accent); }
.task-item.done .task-checkbox {
background: var(--success);
border-color: var(--success);
}
.task-item.done .task-label { text-decoration: line-through; color: var(--muted); }Three states: default (empty + strong border), hover (accent border, hint of intent), done (filled green + strikethrough). The hover state matters — without it, learners aren't sure the checkbox is clickable.
css
.task-checkbox {
width: 18px; height: 18px;
border: 1.5px solid var(--border-strong);
border-radius: var(--r-sm);
display: grid; place-items: center;
transition: all 120ms ease;
}
.task-item:hover .task-checkbox { border-color: var(--accent); }
.task-item.done .task-checkbox {
background: var(--success);
border-color: var(--success);
}
.task-item.done .task-label { text-decoration: line-through; color: var(--muted); }三种状态:默认(空+粗边框)、悬停(强调色边框,提示可点击)、已完成(绿色填充+删除线)。悬停状态很重要——没有它,学习者不确定复选框是否可点击。
5. Goal Badge (Green ✓)
5. 目标徽章(绿色✓)
css
.learning-goal::before {
content: '✓';
display: inline-block;
width: 20px; height: 20px;
background: var(--success-soft);
color: var(--success);
border-radius: 999px;
text-align: center;
line-height: 20px;
margin-right: 8px;
font-weight: bold;
}Use the green-on-light-green disc consistently for "learning outcomes" / "you'll be able to ...". Don't reuse for "completed" — that's 's job. Green has two distinct semantic uses which must look different: goal (badge prefix) vs done (filled checkbox).
task-checkboxcss
.learning-goal::before {
content: '✓';
display: inline-block;
width: 20px; height: 20px;
background: var(--success-soft);
color: var(--success);
border-radius: 999px;
text-align: center;
line-height: 20px;
margin-right: 8px;
font-weight: bold;
}始终使用浅绿底绿字的圆形徽章标记「学习成果」/「你将能够...」。不要将其复用为「已完成」标记——那是的职责。绿色有两种不同的语义用途,必须区分开来:目标(徽章前缀)与已完成(填充复选框)。
task-checkboxDark Mode Strategy
暗黑模式策略
css
:root { /* light tokens here */ }
[data-theme="dark"] {
--bg: oklch(16% 0.014 250);
--surface: oklch(19.5% 0.014 250);
--fg: oklch(96% 0.005 250);
--border: oklch(28% 0.014 250);
/* accents usually stay the same — accent-deep may flip to brighter */
--accent-deep: oklch(72% 0.18 255);
}Use attribute, not : a manual toggle is the source of truth. Auto-following OS theme means the user can't decide per-site. The toggle reads/writes localStorage.
[data-theme]prefers-color-schemeWhat flips in dark mode:
- ✅ All surface tokens (bg / surface / fg / muted / border)
- ✅ (the high-contrast variant) — flip to a brighter L value
accent-deep - ❌ Status colors (success / danger / warning) — these are semantic, keep their hue; the variant naturally darkens because of the surface change
-soft - ❌ — the dual-accent identity should survive dark mode (the orange brand stays orange)
accent-2
What stays the same:
- All geometry tokens (radii, sidebar width, shadow definitions — though shadow opacity may need tuning)
- All component layouts and structure
The rule of thumb: token values change, component CSS does not. If you find yourself writing , the abstraction has leaked — refactor the component to use tokens for the property that's varying.
[data-theme="dark"] .task-checkbox { ... }css
:root { /* 浅色模式Token */ }
[data-theme="dark"] {
--bg: oklch(16% 0.014 250);
--surface: oklch(19.5% 0.014 250);
--fg: oklch(96% 0.005 250);
--border: oklch(28% 0.014 250);
/* 强调色通常保持不变——accent-deep可能会调亮 */
--accent-deep: oklch(72% 0.18 255);
}使用属性,而非:手动切换是最终的判断标准。自动跟随系统主题意味着用户无法按站点自定义。切换按钮会读取/写入localStorage。
[data-theme]prefers-color-scheme暗黑模式中需要切换的内容:
- ✅ 所有表层Token(bg/surface/fg/muted/border)
- ✅ (高对比度变体)——调亮亮度值
accent-deep - ❌ 状态颜色(success/danger/warning)——这些是语义化的,保持色相不变;变体会随背景变化自然变暗
-soft - ❌ ——双强调色的标识应在暗黑模式下保留(橙色品牌色保持橙色)
accent-2
保持不变的内容:
- 所有几何Token(圆角、侧边栏宽度、阴影定义——不过阴影透明度可能需要调整)
- 所有组件布局和结构
经验法则:Token值变化,组件CSS不变。如果你发现自己在写,说明抽象层已经失效——重构组件,使用Token来控制变化的属性。
[data-theme="dark"] .task-checkbox { ... }Cross-Format Token Reuse (Web → Ebook)
跨格式Token复用(网页→电子书)
The ebook print CSS () reads the same tokens. Specifically:
course-ebook-publishingcss
/* style-ebook.css (print only) */
@media print {
:root {
/* Override only what print needs differently */
--bg: white;
--surface: white;
/* But colors of badges, prompts, headings stay the same */
}
.prompt-block { /* same .prompt-block style — looks identical to web */ }
.learning-goal::before { /* same green disc */ }
}Why: a learner who sees the web first, then opens the PDF handbook, should feel "same product". If web is orange-PROMPT and PDF is gray-PROMPT, the visual brand is shattered.
The corporate edition () does the same — even with brand-customised assets, the design tokens remain.
course-corporate-edition电子书打印CSS()读取相同的Token。具体如下:
course-ebook-publishingcss
/* style-ebook.css(仅打印) */
@media print {
:root {
/* 仅覆盖打印需要的不同设置 */
--bg: white;
--surface: white;
/* 但徽章、提示框、标题的颜色保持不变 */
}
.prompt-block { /* 相同的.prompt-block样式——与网页外观一致 */ }
.learning-goal::before { /* 相同的绿色圆形徽章 */ }
}原因:先浏览网页,再打开PDF手册的学习者应该觉得「这是同一个产品」。如果网页是橙色PROMPT而PDF是灰色PROMPT,视觉品牌就会被破坏。
企业版()也是如此——即使有品牌定制资源,设计Token也保持不变。
course-corporate-editionThree Decisions That Sound Small But Aren't
三个看似微小却至关重要的决策
Decision 1: color-mix(in oklab, X 18%, transparent)
for soft tints
color-mix(in oklab, X 18%, transparent)决策1:使用color-mix(in oklab, X 18%, transparent)
生成柔和淡色
color-mix(in oklab, X 18%, transparent)Don't hand-write . Use so tints derive from the source token:
rgba(...)color-mixcss
background: color-mix(in oklab, var(--accent-2) 18%, transparent);When you eventually re-tune , every tint follows. With manual rgba, you'd have 50 places to update.
--accent-2不要手动编写。使用让淡色从源Token派生:
rgba(...)color-mixcss
background: color-mix(in oklab, var(--accent-2) 18%, transparent);当你最终调整时,所有淡色都会自动跟随变化。如果手动使用rgba,你需要修改50个地方。
--accent-2Decision 2: No grid system, just --content-max
--content-max决策2:不使用网格系统,仅用--content-max
--content-maxAvoid bringing in a 12-column grid framework. For a teaching site with linear reading flow, is enough. Columns appear locally via inside specific components (figure grid, tool gallery) — but the page itself is a stream.
max-width: var(--content-max); margin: 0 autogrid-template-columns避免引入12列网格框架。对于线性阅读流程的教学网站,就足够了。列布局仅在特定组件内部使用实现(如图形网格、工具库)——但页面本身是流式布局。
max-width: var(--content-max); margin: 0 autogrid-template-columnsDecision 3: Animation budget = "almost none"
决策3:动画预算=「几乎为零」
Allowed:
- on scroll (one-time per element)
fade-in - Hover micro-interactions (color / shadow shift, 120–200ms)
- Sidebar slide (transform, 200ms)
NOT allowed:
- Page transitions between sections
- Decorative idle animations
- Anything > 400ms
Teaching content is dense; animation is a distraction tax. Spend the attention budget on content, not motion.
允许的动画:
- 滚动时的淡入(每个元素仅触发一次)
- 悬停微交互(颜色/阴影变化,120–200ms)
- 侧边栏滑动(transform,200ms)
不允许的动画:
- 页面间过渡动画
- 装饰性闲置动画
- 任何超过400ms的动画
教学内容密度高;动画会分散注意力。把注意力预算花在内容上,而非动效上。
Anti-Patterns
反模式
- Inventing a new color for "this one section" — pull from existing tokens or refactor to add a properly-named token. Drive-by hex values rot the system.
- Using for content-emphasis (like PROMPT badge) — collapses the dual-accent semantic. Use
--accent.--accent-2 - Different font for code blocks — see typography section. Use the same stack with /
font-weightfor differentiation, or accept the visual cost.letter-spacing - Manually styling dark mode per component — see dark mode section. If a component needs special dark-mode handling, the component is using a non-tokenised value somewhere.
- Forgetting variants — every accent / status color needs a soft variant. Without it, designers reach for ad-hoc opacity values.
-soft
- 为「某个特定区域」发明新颜色——从现有Token中选取,或重构添加一个命名规范的新Token。随意使用十六进制值会破坏系统。
- 使用强调内容(如PROMPT徽章)——会混淆双强调色的语义。应使用
--accent。--accent-2 - 代码块使用不同字体——参见排版部分。使用同一字体栈,通过/
font-weight区分,或接受视觉差异。letter-spacing - 为每个组件手动设置暗黑模式样式——参见暗黑模式部分。如果组件需要特殊的暗黑模式处理,说明该组件在某处使用了非Token化的值。
- 忘记添加变体——每个强调色/状态色都需要
-soft变体。没有它,设计师会使用临时的透明度值。-soft
Hand-off
交接说明
When this skill is consumed by another skill (SPA / interactions / ebook / corporate):
- Reference tokens, never raw values.
:root - If you find yourself writing a literal hex or
#..., you've broken the system — either it belongs as a new token, or you're recreating an existing one.rgb(...) - New components should compose existing patterns (glass-card + prompt-block + task-list) before inventing.
The token file (the block) is the single source of truth. Print it on the wall. Re-tune values when the brand evolves, but never widen the token set casually.
:root { ... }当其他Skill(SPA/交互/电子书/企业版)使用本Skill时:
- 引用Token,而非原始值。
:root - 如果你发现自己在写字面量十六进制值或
#...,说明你破坏了系统——要么应该添加一个新Token,要么你在重复创建已有的Token。rgb(...) - 新组件应先组合现有模式(glass-card+prompt-block+task-list),再考虑创建新样式。
Token文件(代码块)是唯一的事实来源。把它贴在墙上。当品牌升级时调整数值,但不要随意扩大Token集合。
:root { ... }