Communitygithub.com

karero/website-design-system

管理网站视觉呈现层:移动端图形、暗黑模式和主题令牌。输出 `BRAND.md` 和令牌块,确保图像、表格和电子邮件混淆符合规范。

website-design-system 是什么?

该技能(karero/website-design-system)专注于定义和维护网站的视觉设计系统,涵盖移动端图形、暗黑模式以及基于 CSS 自定义属性的主题令牌。它强制使用 WebP/AVIF 格式(通过 Astro 的 `astro:assets`)并确保图像大小与显示尺寸匹配,以避免布局偏移和 CLS/LCP 问题。暗黑模式是一等公民:所有颜色通过令牌定义,系统在首次绘制前从 `localStorage` 或系统偏好设置主题,并使用 no-FOUC 脚本防止闪烁。每个文本/背景对都通过 WCAG AA 对比度测试。该技能还解决了多语言文本长度的响应式问题,特别是德语等语言比英语长 20-35% 时,要求使用弹性宽度并启用连字符和自动换行属性。表格有两种风格:`stack`(用于句子,在窄屏幕上自动堆叠)和 `figures`(用于短数字,保持表格布局)。`tables.spec.ts` 测试确保所有表格具有正确的 ARIA 角色、标签,并且不会水平滚动。图像必须包含 `alt` 属性,通过 `EmailLink.astro` 组件混淆电子邮件地址,以阻止爬虫抓取。该技能支持 Cursor 和 Claude Code 等平台,输出 `BRAND.md` 和令牌块,并包含一个图像生成子技能。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/karero/croftweaver/tree/HEAD/skills/website-design-system

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

网站设计系统

管理视觉呈现层:移动端图形、暗黑模式和主题令牌。输出/维护 BRAND.md(模板:new-website 技能的 templates/brand.md)以及该技能 templates/astro/src/styles/global.css 中的令牌块。图像规则如下(通过 Astro 的 astro:assets 使用 WebP/AVIF);images.spec.ts 测试强制执行这些规则。如需生成图像资源,请使用 image 技能。

暗黑模式(一等公民)

  • 令牌,而非硬编码颜色。 所有颜色通过 CSS 自定义属性流动;亮色是 :root 默认值,暗色在 :root[data-theme="dark"] 下覆盖,此外还有一个 @media (prefers-color-scheme: dark) 代码块用于无 JavaScript 的访客。启动器已提供这种精确的结构。
  • 无 FOUC 脚本 在 <head> 中从 localStorage.theme 或系统偏好设置 data-theme(已在 Base.astro 中配置)。切换开关写入 localStorage.theme(启动器未提供;如果添加,请在隐私页面的第 3 节说明)。
  • 两种主题均通过对比度测试: 每个文本/背景对都通过 WCAG AA(正文 4.5:1,大/UI 元素 3:1)。在亮色中通过的颜色在暗色中通常失败——可访问性测试在完整的亮色+暗色矩阵中运行,因此请检查两者。

移动端与响应式图形

  • 移动端优先: 从 360px 开始设计;触摸目标 ≥ 44px;无水平滚动。在 360 / 768 / 1280 分辨率下验证(使用 preview_resize)。
  • 现代格式: 照片使用 WebP(或 AVIF)优于 JPEG/PNG。
  • 尺寸与显示匹配,而非源文件。 切勿将 2000px 的图像放入 80px 的空间;生成宽度变体并使用 srcset/sizes(或 <picture>)。
  • 无布局偏移: 设置显式的 width/height 属性,以便在图像加载前预留元素框(保护 CLS / LCP)。Astro 的 <Image> 会自动设置;images.spec.ts 要求这些属性(仅使用 CSS 的 aspect-ratio 无法通过测试)。
  • 懒加载与立即加载: 折叠内容以下使用 loading="lazy";LCP/首屏图像使用 fetchpriority="high" 立即加载(不要对其使用懒加载)。
  • 每个图像都有替代文本(仅纯装饰图像使用 alt="")。
  • 字体: 自托管 woff2 并设置 font-display: swap;仅预加载首屏使用的 1-2 种字体。避免因后期字体替换导致布局偏移。

文本长度响应式(翻译后的副本)

  • 翻译后的文本通常更长。 德语(以及许多其他语言)通常比等效的英文副本长 20-35%。一个适合英文占位符文本的按钮、导航链接或卡片,在真实翻译副本替换后,会悄然溢出、换行混乱或被截断。
  • 优先使用弹性宽度。 对包含翻译文本的任何元素使用 min-width / flex / grid auto/fr 尺寸,而不是针对英文字符串设置固定 width。
  • 溢出 ≠ 宽度: 弹性尺寸无法阻止单个长复合名词(Datenschutzerklärung)撑破窄列——这需要 hyphens: auto(通过 Base.astro 已设置的 lang 属性针对每种语言正确配置)以及后备的 overflow-wrap: break-word;启动器的 global.css 在 body 上同时提供了这两者。表格单元格会关闭连字符(参见表格)。
  • 不要仅依赖 white-space: nowrap + text-overflow: ellipsis 来处理导航链接或按钮标签——截断导航链接通常不可接受(访客将无法知道其目的地)。对于内容截断是可接受权衡的场景(例如表格单元格)可以接受,但不适用于导航。
  • 使用真实的翻译标签进行验证,而非英文占位符。 当网站部署了 astro-i18n-setup 的 LanguageSwitcher.astro 或任何双语/多语言导航时,请使用每种语言实际发布的副本检查 360/768/1280 分辨率下的布局——而不仅仅是英文占位符。

表格

所有表格共用一种样式;页面中不应包含任何表格的布局 CSS。它位于启动器的 src/styles/tables.css 中(由 Base.astro 在 global.css 之后导入),并由 tests/tables.spec.ts 检查。在此部分之前创建的网站需要复制 tables.css 文件,将其导入行添加到布局中,并首先移除每个页面自己的表格 CSS。

两种类型,根据单元格内容区分:

  • stack(句子):在屏幕宽度超过 40rem 时显示为表格;低于该宽度时,每行堆叠,行标题作为标题,每个单元格显示在其列名下方。四列散文无法共享 320px 空间。
  • figures(短数字,数字单元格添加 class="num"):在手机上保持表格布局,必须适应 320px 宽度。如果不再适应,将其改为 stack;滚动条不是解决方案。stack figures 一起使用可实现堆叠布局下的数据显示样式。

标记,每个表格:

<div class="table-wrap stack" role="region" aria-label="表格内容说明" tabindex="0">
  <table role="table">
    <thead role="rowgroup"><tr role="row">
      <th scope="col" role="columnheader">{cols[0]}</th><th scope="col" role="columnheader">{cols[1]}</th>
    </tr></thead>
    <tbody role="rowgroup">{rows.map((r) => (
      <tr role="row"><th scope="row" role="rowheader">{r.item}</th><td role="cell" data-label={cols[1]}>{r.text}</td></tr>
    ))}</tbody>
  </table>
</div>
  • 将列名写在一个列表中,同时用于表头和每个 data-label:堆叠单元格的标签必须等于其列表头,测试会比较两者。figures 表格不需要每个单元格的角色和 data-label。
  • 堆叠表格不再是 display: table。这些角色是当布局改变时浏览器丢弃表格情况下的后备方案;其有效性未经验证。在 Chromium 中,在真实表格上测量一次,可访问性树在没有角色时仍保留表格。
  • class="tap" 应用于单元格中独立的链接,使其在手机上成为 44px 的触摸目标。nowrap 可将短值(1, 3, 6)保持在一行。long-head(与 stack 一起使用)在行标题为句子时加宽第一列。
  • 单元格中的单词不会连字符化。正文的 hyphens: auto 会将窄的第一列压缩成碎片(“An-thropic”),因此代码块在此处设置 hyphens: manual。
  • 来自外部且无法承载此标记的表格页面应放入规范中的 TABLE_EXEMPT,并说明原因。PAGES 保持完整:站点地图和 llms.txt 检查需要其中的每个活跃路由。

tables.spec.ts 检查的内容:每个表格都是一个 .table-wrap 的其中一种类型,具有其区域、标签和 tabindex,每个表头单元格有 scope="col",每行第一个单元格为 <th scope="row">,其余为 <td>;堆叠表格具有角色,并且每个单元格的标签等于表头;在 360 和 320px 下,没有页面或表格水平滚动;在 641px 及以上,堆叠表格再次显示为表格,显示表头行且单词未被断开(这捕获了诸如 overflow-wrap: anywhere 之类的规则,该规则允许列挤压单词);没有单元格使用 hyphens: auto。它还测试添加到主页面的固定 CSS,并在两种主题下使用 axe 进行测试,因此即使没有表格的网站也能证明代码块的有效性。无头 Chromium 不会连字符化,因此连字符保护读取计算后的样式,而非布局。Safari 和 VoiceOver 未检查。

电子邮件混淆(隐藏地址以防爬虫)

切勿在 HTML 源代码中放置纯文本电子邮件地址或 mailto:your@addr——爬虫会立即抓取这些地址用于发送垃圾邮件。通过 EmailLink.astro 组件(new-website 技能 templates/astro/ 目录下的 src/components/EmailLink.astro,加上其 lib/obfuscate.ts 辅助程序)渲染每个地址:地址在构建时被反转并 base64 编码,在浏览器中重新组装,因此提供的 HTML 不包含可读的地址。无 JavaScript 的访客会看到一个仍然可用的“name [at] domain [dot] com”提示。

<EmailLink address="[email protected]" subject="项目咨询" text="给我们发邮件" />

规则:构建后的 HTML 中零个原始 mailto: 链接和零个文字 @-地址——website-qa 会检查此项。任何不希望被抓取的电话号码也采用相同的方式。

品牌令牌

将 BRAND.md 的调色板镜像到令牌块中并保持同步。定义:品牌色(固定),以及每个主题的标题色/墨色/弱化色/强调色/链接色/线条色/背景色/背景柔和色/表面色。强调色和链接色必须在两种主题下均能通过背景的 AA 对比度测试,这就是为什么每个主题都有自己颜色的原因。可选的 website-brand-kit 通过检查执行镜像操作:其读取操作读取 BRAND.md 的表格,在两种主题下将所有文本颜色与每个背景的 4.5:1 对比度进行比较,并将这些值写入 global.css 的所有三个颜色块(亮色、暗色以及面向无 JavaScript 访客的暗色块)。手动操作时,请一起更改所有三个块。

完成的定义

BRAND.md 已填写并与令牌块一致;图像为 WebP 格式、尺寸正确、懒加载/立即加载正确、具有替代文本;可访问性测试(亮色+暗色)通过;布局在 360/768/1280 下保持不变且无偏移;每个表格为 stack 或 figures 且 tables.spec.ts 通过。性能指标(FCP/LCP)已在 website-qa 中验证。布局在 360/768/1280 下使用每种发布语言的真实(而非占位符)副本进行验证,而不仅仅是默认区域设置。

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相关技能