news 2026/10/23 11:11:56

Webstudio Craft 规范实战指南:在项目中应用 Craft 标准构建可维护、可复用的设计系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Webstudio Craft 规范实战指南:在项目中应用 Craft 标准构建可维护、可复用的设计系统
  • 低代码
  • 前端

【免费下载链接】webstudio

Open source website builder and Webflow alternative. Webstudio is an advanced visual builder that connects to any headless CMS, supports all CSS properties, and can be hosted anywhere, including with us.

项目地址:https://gitcode.com/gh_mirrors/we/webstudio
点击查看免费下载

Craft 是 Webstudio 官方发布的通用规范(见 Craft),它定义了 CSS 变量、Token 与 Local 样式的命名和使用规则,让人与共享的 Marketplace 资源可以在不引入互不兼容约定(incompatible conventions)的前提下协同工作。本篇指南以 docs/university/craft-guide.md 为主线,讲解如何在 Webstudio 项目中从零启用 Craft:先以 Craft Style Guide 为起点,把语义变量(semantic variables)与复合 Token(composite Tokens)映射到你的项目,再结合仓库中的规范原文与设计令牌文档,掌握 Style Guide 维护、Navigator 命名规范、Craft Library 模板复用等一整套可落地的实战流程。读完本文,你将能够按照 Craft 标准组织项目结构、命名变量与 Token、维护可发布的样式库,并让页面模板在不同项目之间平滑移植。

开始前的准备:理解 Craft 的三层架构

在动手操作之前,先明确 Craft 的架构基础。Craft 把样式系统分为三层,从下往上分别是:

Theme variables(主题变量) ↓ Semantic variables(语义变量) ↓ Composite Tokens(复合 Token)
  • 主题变量(Theme variables):存放让一个主题区别于另一个主题的取值,可以包含字面量,也可以引用调色板变量(如 Open Props 提供的变量)。主题实现可以使用私有派生变量(private derivation variables)来归一化、约束或变换公共主题输入,但复合 Token 不得直接消费它们,可复用资源也不得依赖它们。
  • 语义变量(Semantic variables):描述"值为什么被使用"而非"值长什么样"。例如错误消息应使用--foreground-negative,而不是直接消费一个红色调色板值。语义变量必须引用公共主题变量、主题层内的私有派生变量或其他语义变量,不应包含独立的字面量设计值。
  • 复合 Token(Composite Tokens):Webstudio 的 Token 可以把多条样式声明打包成一个可复用样式源,Craft 称之为复合 Token,以区别于存在 CSS 变量中的单个值。复合 Token 在存在合适语义变量时必须消费语义变量,不应直接消费调色板或主题变量。

此外还有一层Local 样式:它用于只属于某个实例的值和声明。当某个决定变得可复用时,就把它提升为 CSS 变量或复合 Token。

组件(Components)、工具类(Utilities)、变体(Variants)和尺寸(Sizes)都是复合 Token 的用途(purpose),而不是架构中额外的层。细节可对照 Craft 原文的 "Architecture" 一节。

快速上手:把 Craft Style Guide 引入你的项目

Craft-guide 给出了明确的六步启动流程,这也是将一个新项目接入 Craft 的最小路径:

  1. 进入Marketplace → Pages → Craft。
  2. 插入Style Guide(样式指南)页面。
  3. 在Global Root上定制主题或调色板变量。
  4. 将 Craft 语义变量映射到主题上。
  5. 使用语义变量和复合 Token 进行构建。
  6. 在 Style Guide 中记录项目的扩展(extensions)。

其中第 3 步提到的Global Root是 Navigator 中层级最高的实例,对所有页面生效。它底层使用:rootCSS 选择器(见 Anatomy of the Webstudio builder 的 "Global root" 一节)。在 Global Root 上定义跨项目共享的变量,是 Craft 推荐的做法;只有当某个变量的含义刻意限定在单页、单个 section 或某个组件子树内时,才把它定义在更近的公共祖先上(见 CSS variables)。

第 6 步强调"文档化扩展":当项目对外发布可复用资源或主题时,必须文档化自己的主题变量;共享的 Marketplace 资源必须声明它们依赖哪些变量,并且不能静默依赖未文档化的项目私有变量。

使用页面模板(Page Template)搭建页面结构

Craft Style Guide 自带一套页面模板,包含导航(navigation)、主区域(main region)、区块(sections)、容器(containers)和页脚(footer)。使用方式如下:

  1. 创建页面时复制模板结构。
  2. 复制模板中的 section 并按内容命名,例如命名为Hero。
  3. 用 Craft 变量和 Token 设计该 section。
  4. 再复制一个干净的模板 section 用于下一个区块。

这套"复制—命名—设计—再复制"的循环,让每个页面都从同一套语义化、可维护的骨架出发,而不是每次从零堆砌。

推荐页面结构

Craft-guide 给出了一个推荐的页面结构,可以直接作为新页面的起点:

Page Wrapper ├── Slot │ ├── Global Styles │ └── Nav ├── Main │ └── Section │ └── Container └── Slot └── Footer

注意其中Container的行为在 Craft 1.2 版本中有过明确约定:为了与 Craft Library 兼容,container改为使用 flex 布局——display设为flex、flex-direction设为column、gap设为var(--gap-m);水平方向的布局调整在 Local 上按需进行(见 Craft changelog)。也就是说,默认的 Container 是纵向排列的 flex 列容器,需要横向排布时请在实例的 Local 样式上覆盖。

维护 Style Guide:命名约定与展示 Token 的隔离

Style Guide 本身也需要被当作一个需要维护的"活文档"来对待:

  • 页面名固定使用Style Guide。
  • 仅用于展示 Style Guide 的 Token,用两个下划线作为前缀,例如__badge或__outline。
  • 这些展示性 Token 绝不能用在已发布的站点上。

这样做的目的是把"规范演示"与"实际产品"隔离开:__前缀形成一道清晰的界限,让任何人(包括未来接入的协作者或复制模板的开发者)一眼就能识别哪些 Token 只是指南的演示道具。

在 Navigator 中命名实例

Craft 对 Navigator 中的实例命名有明确的语义化要求,核心原则是用标题大小写(title case)和语义标签命名:

  • 为 Box、Slot、HTML Embed 和 Collection 实例赋予能描述其用途的名称。
  • 容器按内容命名,而不是按位置或外观命名(例如Cards而不是Right Column)。
  • 重复内容使用复数父级 + 单数子级,例如一个Cards容器里放多个Card项。
  • 使用section元素的 Box 以Section作为前缀,例如Section Hero。
  • 一个 HTML Embed 实例只负责一个用途,并且它的代码要以一条描述该用途的注释开头。

这些约定与 Anatomy of the Webstudio builder 中的建议一脉相承——Navigator 提供了整个页面的层级总览,双击实例即可重命名,使用 "Hero Section"、"Contact Form" 这类语义化名称能让项目结构更容易理解和维护。按照上述命名规范组织结构,是后续把 section 打包进 Craft Library、跨项目复用的前提。

使用 Craft Library:基于规范的可复用区块集

Craft Library是按 Craft 标准构建的区块模板(section templates)集合,可在 Marketplace 中获取。它是一个独立的 Marketplace 资源,与一般的页面模板、集成模板并列为三类模板之一。

Craft Library 对模板有两条硬性要求(这也是判断一个 section 是否"符合 Craft"的试金石):

  • 模板不得包含未经解释的硬编码设计值(unexplained hardcoded design values)。
  • 模板必须消费已文档化的 Craft 变量或已文档化的扩展,这样当它被插入另一个符合规范的项目时,section 会自动适应该项目的主题。

换句话说,一个 Craft 模板携带的是"语义契约"而不是"具体长相"。当你从 Craft Library 插入一个 section 时,它引用的是你项目中已定义的语义变量,因此主题一变,整个 section 跟着变。

从 Marketplace 的 Token 冲突处理机制(见 Marketplace)也能看到配套保障:插入使用设计令牌的模板时,如果模板中的 Token 名与项目已有 Token 冲突,Webstudio 会弹出冲突解决对话框,提供"重命名模板 Token"、"覆盖现有 Token"、"保留现有 Token"三种选择。这保证了 Craft Library 的模板在并入项目时不会破坏已有的设计。

如果你想反向贡献,可以参考 Contributing to the Marketplace 了解如何提交自己的 Craft 资源。

深入:Craft 变量命名语法与颜色语义

为了让变量名在语义层上可读、可扩展,Craft 规定了严格的命名语法。CSS 变量名必须:

  • 使用 kebab-case(连字符小写命名)。
  • 使用完整单词,除非缩写属于 Craft 批准的词汇表。
  • 在语义层描述用途而非视觉外观。

语义颜色变量的命名语法

--{category}-{purpose}[-{state}]
  • Category(类别):必须是foreground、background、border、overlay之一。
  • Purpose(用途):一个或多个 kebab-case 词,描述该颜色可复用的含义;复合用途把变体放在基础用途之后,例如negative-subtle。
  • State(状态):可选的结尾后缀,只能是hover、pressed、selected、disabled、focus。只有当项目的已文档化注册表把该名称声明为状态变量时,才把最后一个词当作状态。例如--overlay-interaction-pressed是一个 pressed 交互遮罩,而--foreground-disabled中的disabled是注册过的用途。

合法示例:

--foreground-primary --overlay-interaction-hover --border-negative --overlay-scrim

调色板与比例(scale)变量使用数字命名:

--blue-10 --size-4

禁止把字面值编码进语义名称:

/* Avoid */ --foreground-gray --background-blue-hover /* Prefer */ --foreground-muted --background-accent

核心颜色变量列表是通用用途的注册表(registry)。扩展必须文档化新增的名称,并说明最后一个词是用途还是状态;扩展可以引入复合用途,但不得重新解释已注册的核心名称。

四类界面颜色与最小核心基线

Craft 把界面颜色组织为四类:

  • Foreground:文本、图标及绘制在背景之上的其他标记。
  • Background:画布、表面、控件和填充状态。
  • Border:边界、分隔线和焦点指示器。
  • Overlay:半透明的交互层与遮罩(scrim)。

通用用途与状态词表如下:

Emphasis purposes: primary, secondary, muted, disabled, inverse Intent purposes: accent, positive, negative, warning, informative Purpose variation: subtle State: hover, pressed, selected, disabled, focus

Craft 特别强调:这个词汇表不是矩阵。只应为"被多个复合 Token 消费的可复用决定"或"明确的无障碍配对"定义语义变量,不要生成类别 × 意图 × 变体 × 状态的每种组合。

通用基线刻意保持精简:

/* Foreground */ --foreground-primary --foreground-secondary --foreground-disabled /* Background */ --background-primary --background-secondary --background-disabled /* Border */ --border-default --border-focus /* Overlay */ --overlay-scrim

意图扩展(intent extensions)通常成组出现,包含前景、背景、边框以及配套的前景名称:

--foreground-negative --background-negative --background-negative-subtle --border-negative --foreground-on-negative

注意foreground-on-*配对变量用于放置在强语义背景上的内容。即使多个配对最终解析为相同的值,也要保持配对显式存在——因为每个配对都定义了一个可独立验证的对比度契约(contrast contract)。

组件状态应尽量在复合 Token 内部用现有语义变量组合出来,而不是为每个背景创建解析后的状态色:

--overlay-interaction-hover --overlay-interaction-pressed --overlay-on-inverse-hover --overlay-on-inverse-pressed

只有当某个状态色独立可复用且无法通过组合表达时,才把它提升到语义层。例如checked、on、current通常可以组合出选中态,invalid通常由 negative 前景色与边框色组合而成——这些组件状态本身不需要新的全局颜色。

从主题派生颜色:保持语义层与主题的连接

语义颜色应当始终与主题保持连接,优先使用别名(aliases)和相对颜色表达式(relative color expressions),而不是复制字面量。Craft 给出了一个完整的推导示例:

:root { color-scheme: light dark; --seed-neutral: oklch(50% 0.01 250); --seed-accent: oklch(50% 0.2 255); --theme-background: light-dark( oklch(from var(--seed-neutral) 98% 0.002 h), oklch(from var(--seed-neutral) 17% 0.012 h) ); --theme-foreground: light-dark( oklch(from var(--seed-neutral) 20% 0.015 h), oklch(from var(--seed-neutral) 94% 0.006 h) ); --theme-accent: light-dark( oklch(from var(--seed-accent) 54% c h), oklch(from var(--seed-accent) 72% calc(c * 0.82) h) ); --background-primary: var(--theme-background); --foreground-primary: var(--theme-foreground); --background-accent: var(--theme-accent); --overlay-interaction-hover: oklch( from var(--theme-foreground) l c h / 6% ); }

这个示例演示了关键原则:只定义一次色相种子(hue seed),再派生出各配色方案的结果。light-dark()在项目支持原生color-scheme时可以在派生表达式之间选择;项目也可以为每个方案覆盖一个小型共享变换配置(transformation profile)。无论如何,不要维护语义层的独立浅色/深色两份拷贝。该示例并不规定固定的种子或主题变量数量,它展示的是"作者输入 → 主题色 → 语义输出"三者之间必须保持的分离。

其他核心变量:布局、焦点与动效

Craft 还保留了一小组可复用的布局、焦点与动效变量:

--gap-xs --gap-s --gap-m --gap-l --spacing-default --focus-width --focus-offset --duration-default --easing-default

这些变量遵循同样的架构:其语义值应在适当时从已文档化的主题或比例输入中派生。其中--spacing-default是 Craft 1.1 引入的,用于共享的容器与卡片内边距(见 Craft changelog)。

交互状态(Interaction States)的语义约定

Craft 要求一致地使用下列语义状态:

状态含义
hover指针设备悬停于交互目标之上。
pressed目标正在被激活。CSS:active映射到pressed。
selected某个选项或条目被选中、当前、勾选或打开。
disabled交互不可用。
focus目标拥有可见的键盘焦点。

像open、pending、invalid以及应用专属状态可能影响多个属性。它们应通过复合 Token 变体来表达,并复用最接近的语义颜色,而不是为每个状态名自动创建一个全局颜色。这与 States and selectors 文档所讲的样式化交互状态的方法相辅相成。

无障碍要求:WCAG 2.2 Level AA

Craft 的一致性(conformance)要求满足WCAG 2.2 Level AA,主题和扩展必须保留无障碍的语义配对。核心要求包括:

  • 正常文本与其背景的对比度至少为4.5:1。
  • 大文本与其背景的对比度至少为3:1。
  • 有意义的非文本界面图形与相邻颜色的对比度至少为3:1。
  • 键盘焦点必须保持可见。
  • 颜色不能是传达状态或信息的唯一手段。
  • 禁用态样式可以弱化,但不得掩盖理解界面所需的信息。
  • 每个受支持的主题都必须满足同样的要求。

Craft 还额外推荐满足 WCAG 2.2 Level AAA 的焦点外观(Focus Appearance)准则:自定义焦点指示器应至少提供 3:1 的对比度变化,且面积至少相当于 2 CSS 像素周长的区域。

foreground-on-*配对变量在这里的意义就在于此:每个配对都是独立可验证的对比度契约,即使多个配对解析为同一个值,也不能合并或省略。

复合 Token 的命名与组合规则

复合 Token 把可复用声明组合在一起,其值应引用 CSS 变量,这样主题变化时无需编辑 Token。命名规则如下表:

用途命名规则示例
Utilitykebab-casemargin-auto,flex-gap-small
Componentkebab-casebutton,input,card
SemanticTitle casePricing Card,Team Member
Variantis-{base}-{name}is-button-secondary
Size{base}-{size}button-small,button-large

配套规则:

  • 变体(variant)必须与其基础 Token 一起使用。
  • 尺寸 Token 应只包含改变尺寸所需的声明。
  • 当一个可复用决定需要多条声明或协调多个状态时,优先使用复合 Token;当只需要一个可复用值时,优先使用 CSS 变量;实例专属的例外使用 Local。

关于 Token 的优先级:当多个 Token 设置同一属性时,最右侧的样式源生效。需要实例覆盖 Token 时,把 Local 放在最后(最右)。这背后的机制在 Design tokens 中有完整展开:你可以把card基础 Token 与is-card-featured、card-small这类变体/尺寸 Token 叠加使用,靠右的 Token 覆盖左侧的冲突属性;要覆盖某个实例时,把 Local 拖到最右侧即可让 Local 样式优先。另外,默认情况下 Token 会被转换为原子样式(atomic styles)输出,显著减少 CSS 体积、加快页面加载,这一点可以在项目设置中配置(见 Design tokens 的 "Exporting human-readable classes")。

扩展与例外(Extensions and Exceptions)

当核心词汇无法表达某个可复用的领域概念时,项目可以扩展 Craft。一个扩展必须:

  1. 遵循同样的命名语法。
  2. 描述用途而非具体的视觉值。
  3. 在可能时复用或派生自现有主题变量与语义变量。
  4. 只有当现有值无法保留预期区分时才引入新的主题值。
  5. 在对外共享时,文档化其含义、支持的状态、无障碍配对和主题行为。

字面量颜色(literal colors)在以下场景是合适的:颜色属于用户内容、外部表示、数据可视化,或属于"必须不随界面主题变化"的功能预览。这些共享例外应被文档化,以免被误认为是缺失的语义变量。

项目专属的扩展不会自动成为 Craft 核心。只有当同一语义需求在无关项目之间也可复用时,才值得把扩展提升为 Craft 核心。

一致性检查(Conformance):判断项目是否符合 Craft

Craft-guide 所依托的规范 Craft 给出了明确的一致性判据。一个项目符合 Craft 当且仅当:

  • 共享复合 Token 在合适的地方使用语义变量。
  • 语义变量从主题层或其他语义变量派生。
  • 主题变化不需要编辑复合 Token。
  • 变量和 Token 名称遵循 Craft 语法。
  • 必要的前景/背景配对满足无障碍规则。
  • 共享扩展与字面量例外已文档化。
  • 可复用资源声明其必需的 Craft 变量和扩展。

一致性并不要求每个项目都定义参考列表中的每一个变量——它只要求每个被消费的变量和扩展都遵循这个契约。这正对应 Craft-guide 开篇的主张:以 Craft Style Guide 为起点,把语义变量与复合 Token 映射到你的项目,项目专属的差异通过文档化扩展来表达,而不是另起炉灶。

版本演进速览

如果你正在升级已有项目,可以参考 Craft changelog 了解规范的演进:

  • Next:定义了 Craft 架构、命名语法、颜色语义、无障碍要求、扩展规则与一致性判据;将 Webstudio Token 定义为复合 Token 并对齐组件/工具/语义/变体/尺寸命名;用--border-default替换--foreground-border,用--border-focus替换--focus-color。
  • 1.2:container改用 flex 以兼容 Craft Library(见上文页面结构部分)。
  • 1.1:新增--spacing-default用于共享容器和卡片内边距。
  • 1.0:发布 Craft。

相关文档

  • Craft – 规范全文,遵循这一通用标准
  • Craft changelog – 查阅标准变更记录
  • Marketplace – 获取 Craft Library 与其他资源
  • Contributing to the Marketplace – 提交你的 Craft 资源
  • Anatomy of the Webstudio builder – 理解 Builder 界面与 Global Root
  • Design tokens – 创建和管理可复用的复合 Token
  • CSS variables – 定义与作用域化可复用值
  • 低代码
  • 前端

【免费下载链接】webstudio

Open source website builder and Webflow alternative. Webstudio is an advanced visual builder that connects to any headless CMS, supports all CSS properties, and can be hosted anywhere, including with us.

项目地址:https://gitcode.com/gh_mirrors/we/webstudio
点击查看免费下载

相关推荐

上一篇:ProtoAttend 源码解析:基于注意力原型学习的可解释模型与置信度估计(google-research/protoattend)
下一篇:CoffeeScript 1.1.3 版本解析:空白排版、类内 super、二进制字面量与模块化重构

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 4:01:13

一文读懂荧光标记脂质:DOPE-FITC与FITC-PEG-DOPE的合成与应用

做纳米药物递送的人,应该都见过DOPE-FITC和FITC-PEG-DOPE这种缩写。我第一次看到的时候也愣了半天,DOPE是磷脂,FITC是荧光染料,连在一起到底是干什么用的?后来真正开始给脂质纳米颗粒做细胞摄取和体内分布追踪&#xf…

作者头像 李华
网站建设 2026/10/21 4:01:11

体系 2 · 排序与结构体 讲义

结构体 排序是普及组的必考核心地基:多关键字排序、数据分组排序、复杂对象排序、贪心前的预处理,几乎都建立在它之上。 学习目标 掌握结构体定义、赋值、结构体数组掌握 sort 默认排序与自定义 cmp掌握单 / 多关键字优先级排序(真题高频&…

作者头像 李华
网站建设 2026/10/21 5:50:27

Redis缓存与数据库一致性实战:方案选型与踩坑总结

1. 缓存命中率上去了,数据却乱了:一致性问题的本质来源我记得第一次在生产环境把Redis缓存铺到订单详情页的时候,效果立竿见影——接口平均耗时从380ms掉到40ms,DB主库的QPS从2万降到3000。正当我沾沾自喜的时候,客服那…

作者头像 李华