网站导航

语法

变量与模式

令牌查找、依赖项交付、inline 替换、继承和模式启用。

本页内容

主题令牌有两个角色:名称让已注册的工具类族可以使用某个值,输出的自定义属性则参与原生 CSS。Master CSS 负责解析类并保留依赖项,浏览器则通过层叠与继承解析自定义属性的值。

本页定义令牌查找、依赖项交付、替换和模式启用。主题说明何时应共享令牌,以及如何创建项目主题;令牌索引则列出预设值。

注册与查找

在顶层 @theme 块声明令牌。声明在 @theme 外的原生自定义属性可用于 CSS,但本身不会注册令牌驱动的类。原生选择器与查询应放在块外。样式表语法见 @theme。

令牌族决定要查找哪个命名空间。键是令牌名称剩余的部分,键内的连字符会保留。

令牌类生成声明
--spacing-cardp-cardpadding: var(--spacing-card)
--radius-cardr-cardborder-radius: var(--radius-card)
--color-brandbg-brandbackground-color: var(--color-brand)
--color-text-actionfg-text-actioncolor: var(--color-text-action)
--color-line-dividerb-line-dividerborder-color: var(--color-line-divider)

text-action 和 line-divider 都是 color 命名空间中的键。outline-line-divider 可以使用 --color-line-divider,但 outline-divider 不会自动插入 line-。两个命名空间中的同一个键可以提供不同值:p-card 和 r-card 分别解析。

@theme {  --spacing-card: 1.5rem;  --radius-card: .5rem;  --color-brand: #1d4ed8;  --color-text-action: var(--color-brand);  --color-line-divider: rgb(0 0 0 / 12%);}
<article class="p-card r-card b(1) b-solid b-line-divider">  <a class="fg-text-action" href="/settings">Settings</a></article>
生成的 CSS
@layer theme {  :root,  :host {    --color-line-divider: light-dark(oklch(0% 0 none / .12), oklch(100% 0 none / .12))  }  :root,  :host {    --spacing-card: 1.5rem;    --radius-card: .5rem;    --color-brand: #1d4ed8;    --color-text-action: var(--color-brand);    --color-line-divider: #0000001f  }}@layer utilities {  .b-line-divider {    border-color: var(--color-line-divider)  }  .r-card {    border-radius: var(--radius-card)  }  .b-solid {    border-style: solid  }  .b\(1\) {    border-width: calc(1 * 1px)  }  .fg-text-action {    color: var(--color-text-action)  }  .p-card {    padding: var(--spacing-card)  }}

族索引提供完整的前缀与命名空间映射。完整 CSS 属性名称不会自动创建令牌族。项目需要新映射时,请用 @utility 注册自定义模式。即使存在同键令牌,w-full 这类固定拼写仍保留固定定义;见类解析。

原生变量不会注册令牌类

两个示例都加载预设工具类族。注册与浏览器变量可用性是两种独立能力。

文字说明
  1. @theme { --spacing-card: 1.5rem; } 在 spacing 命名空间注册 card 键,使 p-card 可用。
  2. :root { --spacing-card: 1.5rem; } 提供原生 CSS 变量,但不会注册 p-card。
  3. 显式原生类 (padding:var(--spacing-card)) 可以使用任一配置提供的变量。

依赖项交付

生成声明通常保留 var() 引用。被使用的受管理令牌会与其传递依赖的受管理令牌一起,输出到 theme 层的 :root, :host 下。

@theme {  --spacing-card: 1.5rem;}
<div class="p-card">Example</div>
生成的 CSS
@layer theme {  :root,  :host {    --spacing-card: 1.5rem  }}@layer utilities {  .p-card {    padding: var(--spacing-card)  }}

令牌被保留时,其重复声明仍按源顺序保留,这些值引用的依赖项也会保留。原生样式表的引用可以保留受管理令牌;原生自定义属性声明与局部覆盖仍属于原本的样式表,并遵循该文件的保留策略。

Master CSS 生成类时不会选择浅色、深色或特定视口的值。检查功能可以报告原始声明与依赖项;没有元素、祖先与浏览器环境,就无法确定计算值。

使用令牌会一并保留其依赖项

箭头表示“引用”,不是执行顺序或层叠优先级。此例没有 static 令牌、安全列表或其他引用方。

文字说明
  1. 主题定义 --color-action: var(--color-brand)、--color-brand: #175cff,以及不相关的 --color-unused。
  2. 使用 fg-action 会在 theme 层保留 --color-action,以及其传递依赖项 --color-brand。
  3. 此例中,不相关的令牌没有使用根,因此不会输出。生成的 color 声明保留 var(--color-action),其值由浏览器解析。

缺失名称与无效值

未知令牌键无法生成匹配的令牌族类。这与合法类输出的 var() 后来在浏览器中解析为无效值不同。继承、循环、回退值和属性值合法性均遵循原生自定义属性规则;保留声明不代表最终计算值一定合法。

继承与限定作用域的别名

用原生选择器声明局部覆盖,相同类就能在不同作用域获得不同值:

@theme {  --color-panel: white;}[data-theme="ocean"] {  --color-panel: #082f49;}
<section data-theme="ocean">  <div class="bg-panel">Ocean panel</div></section>

派生值

--color-link: var(--color-brand) 这类别名先在声明该别名的元素上解析,再继承计算值。仅在后代元素覆盖 --color-brand,不会重新绑定已继承的别名。如果别名应由局部 brand 派生,请在后代作用域重新声明它。

相同作用域规则也适用于 color-mix() 这类派生表达式:

@theme {  --color-brand: #1d4ed8;  --color-link: var(--color-brand);  --color-link-hover: color-mix(in oklab, var(--color-brand), black 15%);}[data-theme="plum"] {  --color-brand: #86198f;  --color-link: var(--color-brand);  --color-link-hover: color-mix(in oklab, var(--color-brand), black 15%);}

这些函数仍是 CSS 表达式。Master CSS 不会为每个编写的作用域分别计算颜色。交互别名示例会并排显示继承与重新绑定的结果。

Inline 替换与 static 交付

inline 改变生成声明引用的内容。static 改变令牌的自定义属性声明是否需要被发现的引用方。这两种行为相互独立。

定义生成的类声明自定义属性交付
@theme保留令牌引用需要时保留
@theme inline将令牌值替换一次替换后的类本身不再需要该令牌声明
@theme static保留令牌引用即使未发现引用方也保留
@theme static inline将令牌值替换一次即使未发现引用方也保留

Inline 替换会移除一层间接引用。替换值内的引用仍由浏览器解析,inline 不会递归地将它们替换为常量。它适用于 Master 生成的声明,包括 @apply 展开;手写原生 CSS 保留原有的 var() 引用。

剩余变量在哪里解析

以下两份配置都定义 --color-brand: var(--app-brand) 并使用 bg-brand,只有 inline 修饰符不同。两种情况下,文档根元素都是蓝色,嵌套 section 将 --app-brand 覆盖为紫红色。

Inline 替换改变剩余引用

两个示例在相同标记中使用 bg-brand。普通令牌继承根元素解析后的值;inline 则让生成声明在应用样式的元素上读取 --app-brand。

文字说明
  1. 两份配置都定义 --color-brand: var(--app-brand)。根元素将 --app-brand 设为 #1d4ed8,嵌套 section 则覆盖为 #86198f。
  2. 使用普通 @theme 时,bg-brand 输出 background-color: var(--color-brand)。根元素将 --color-brand 计算为蓝色,嵌套引用方继承该计算值。
  3. 使用 @theme inline 时,bg-brand 输出 background-color: var(--app-brand)。使用它的元素读取从 section 继承的紫红色值。
  4. 色样显示最终背景结果。图中的根元素值是计算值,并不表示编译器会计算颜色。

使用普通 @theme 时,生成声明读取 --color-brand。该令牌的 var(--app-brand) 在根元素解析,嵌套元素继承最终得到的蓝色值。

@theme {  --color-brand: var(--app-brand);}:root {  --app-brand: #1d4ed8;}[data-theme="plum"] {  --app-brand: #86198f;}
<section data-theme="plum">  <div class="bg-brand">Inherited blue</div></section>
生成的 CSS
:root {  --app-brand: #1d4ed8;}[data-theme="plum"] {  --app-brand: #86198f;}@layer theme {  :root,  :host {    --color-brand: var(--app-brand)  }}@layer utilities {  .bg-brand {    background-color: var(--color-brand)  }}

使用 @theme inline 时,生成声明直接在应用样式的元素上读取 --app-brand,获得其 section 提供的紫红色值。

@theme inline {  --color-brand: var(--app-brand);}:root {  --app-brand: #1d4ed8;}[data-theme="plum"] {  --app-brand: #86198f;}
<section data-theme="plum">  <div class="bg-brand">Local plum</div></section>
生成的 CSS
:root {  --app-brand: #1d4ed8;}[data-theme="plum"] {  --app-brand: #86198f;}@layer utilities {  .bg-brand {    background-color: var(--app-brand)  }}

外部引用方需要发现流程看不到的令牌时,可独立使用 static。支持的形式与定义作用域见主题修饰符。

模式启用

模式是编写的 CSS 作用域或条件,不是第二个令牌命名空间。更改令牌值与将规则限制于某个模式,是独立操作。

机制改变的内容启用条件
原生自定义属性覆盖该作用域中继承的值编写的选择器或原生查询
light-dark() 令牌选取的颜色值元素实际使用的配色方案
预设 @dark 或 @light 后缀规则是否可应用系统 prefers-color-scheme 媒体查询
通过 @apply(--name) 使用的选择器混入生成规则在哪里匹配与混入中编写的选择器完全一致

手动作用域与规则包裹

bg-surface 这类令牌类跟随其继承的变量。若只想在 ocean 作用域应用其他声明,请在混入中明确编写该作用域。& 表示生成的选择器,下方后代分支是有意编写的,不是 Master CSS 插入的。

@theme {  --color-surface: white;}[data-theme="ocean"] {  --color-surface: #082f49;}@mixin --ocean {  &:where([data-theme="ocean"], [data-theme="ocean"] *) {    @contents;  }}
<section data-theme="ocean">  <div class="bg-surface p(16)@apply(--ocean)">Ocean panel</div></section>
生成的 CSS
[data-theme="ocean"] {  --color-surface: #082f49;}@layer theme {  :root,  :host {    --color-surface: white  }}@layer utilities {  .p\(16\)\@apply\(--ocean\):where([data-theme="ocean"], [data-theme="ocean"] *) {    padding: calc(16 * 1px)  }  .bg-surface {    background-color: var(--color-surface)  }}

令牌覆盖改变背景值,混入改变内边距应用的位置,两种机制都不会定义另一种。包裹参数与放置方式见工具类与混入。

系统偏好与手动配色方案

完整预设提供原生 color-scheme 规则:根元素允许 light dark,data-theme="light" 或 data-theme="dark" 则将区域固定为指定配色方案。令牌可用 light-dark(white, #111827) 跟随该方案。由浏览器选择值,不需要第二个类。原生行为见 light-dark()。

即使位于手动主题区域,预设的 @dark 和 @light 后缀仍是系统媒体查询。更改 data-theme 不会启用它们。颜色会演示手动启用与嵌套区域。

局部重叠与 Shadow DOM

重叠作用域遵循普通层叠,包括层顺序与选择器优先级。选择器描述了主题,并不代表局部值就自动具有更高优先级。见层叠层。

默认主题声明包含 :host。请明确编写限定作用域的 host 覆盖,并在 shadow tree 中加载所需样式表:

@theme {  --color-panel: white;}:host([data-theme="dark"]) {  --color-panel: #111827;}

令牌不会替代资源交付。原生关键帧及其依赖保留方式,见关键帧契约;样式表保留方式则见原生 CSS 裁剪。