
# 主题与自定义

Tailwind 的主题是一组扁平的 CSS 变量。你可以通过输入 CSS 中的 `@theme { … }` 块来扩展或替换它，通过主题函数在 CSS 中引用这些值，并从 PHP 读取解析后的值。这里没有 JavaScript 配置文件——主题完全位于 CSS 中。

## `@theme` 块

`@theme` 块会将设计令牌声明为 CSS 自定义属性。每个变量的命名空间前缀（`--color-*`、`--font-*`、`--breakpoint-*`、`--spacing-*`、……）会告知 Tailwind 该令牌对应哪些实用工具和变体。

```php
use TailwindPHP\tw;

$css = tw::generate('<div class="bg-brand text-brand xs:flex">', '
    @import "tailwindcss";

    @theme {
        --color-brand: #3b82f6;
        --font-heading: "Inter", sans-serif;
        --breakpoint-xs: 20rem;
        --spacing-huge: 10rem;
    }
');
```

每个令牌都会在其命名空间下注册实用工具。上面的示例会提供 `bg-brand`、`text-brand`、`border-brand`、`font-heading` 系列、`xs:` 响应式变体，以及 `p-huge`/`m-huge` 间距——只有当类名出现在你的内容中时才会生成。

```css
/* bg-brand resolves to the theme variable */
:root, :host {
  --color-brand: #3b82f6;
}
.bg-brand {
  background-color: var(--color-brand);
}
```

`--breakpoint-xs` 令牌会直接注册 `xs:` 变体：

```css
@media (min-width: 20rem) {
  .xs\:flex {
    display: flex;
  }
}
```

### 常见命名空间

| 命名空间 | 对应项 |
|-----------|-------|
| `--color-*` | `bg-*`、`text-*`、`border-*`、`fill-*`、`stroke-*`、…… |
| `--font-*` | `font-*` 系列实用工具 |
| `--text-*` | `text-*` 字号实用工具 |
| `--breakpoint-*` | 响应式变体（`sm:`、`md:`、自定义 `xs:`） |
| `--spacing-*` | 命名间距值（`p-huge`、`m-huge`） |
| `--radius-*` | `rounded-*` 实用工具 |
| `--shadow-*` | `shadow-*` 实用工具 |

### 清除命名空间

将命名空间通配符设为 `initial`，会在添加你自己的令牌之前移除 Tailwind 在该命名空间中的默认值。这样你就可以从空白调色板开始：

```css
@theme {
    /* Drop every default color, then define only what you need */
    --color-*: initial;
    --color-brand: #3b82f6;
    --color-ink: #111827;
}
```

`--*: initial;` 会清除整个主题。对于非通配符键（`--color-red-500: initial;`），单个 `initial` 值只会移除该令牌。`-*` 通配符的值只能是 `initial`，其他任何值都会报错。

## 在 CSS 中读取主题值

### `theme()`

旧版 `theme()` 函数使用点号表示法，根据 v3 风格的命名空间读取值。它会在编译时解析为令牌的值，因此可用于任何需要值的位置，包括自定义规则和其他声明。

```php
$css = tw::generate('<div class="callout">', '
    @import "tailwindcss";
    .callout { color: theme(colors.red.500); }
');
```

```css
.callout {
  color: oklch(63.7% .237 25.331);
}
```

点号路径会映射到底层变量（`colors.red.500` → `--color-red-500`，`fontFamily.sans` → 无衬线字体系列）。支持不透明度修饰符：`theme(colors.red.500 / 50%)`。也可以通过第二个参数传入回退值：`theme(colors.brand, #000)`。如果路径无法解析且未提供回退值，使用它的候选项就会被丢弃。

### `--theme()`

`--theme()` 根据 CSS 自定义属性名称读取主题变量，默认返回 `var()` 引用，因此该值在运行时仍可覆盖：

```css
.btn { color: --theme(--color-brand); }
/* → color: var(--color-brand); */
```

添加 `inline` 可用解析后的值替代 `var()` 引用：`--theme(--color-brand inline)`。第二个参数是回退值（`--theme(--color-brand, #000)`）；`initial` 回退值会特殊处理——注入到嵌套的 `var()` 引用中，这些引用本身会解析为 `initial`。在 at-rule（`@media`、`@container`）内部，`--theme()` 始终会内联解析，因为 `var()` 在这些前导部分中无效。

### `--spacing()`

`--spacing(n)` 将主题的基础间距单位（`--spacing`）乘以 `n`：

```css
@utility my-gap { gap: --spacing(4); }
/* → gap: calc(var(--spacing) * 4); */
```

乘数为 `1` 时会解析为基础变量本身（`--spacing(1)` → `var(--spacing)`，这也是 `p-1` 输出的内容）；`0` 则会解析为纯零长度。

这与内置间距实用工具使用的计算方式相同，因此自定义值与 `p-4`、`m-4` 等保持一致。

### `--alpha()`

`--alpha(color / opacity)` 使用 oklab 色彩空间中的 `color-mix()` 对颜色应用不透明度：

```css
@utility tint { color: --alpha(var(--color-red-500) / 50%); }
```

```css
.tint {
  color: #fb2c3680;
}
@supports (color: color-mix(in lab, red, red)) {
  .tint {
    color: color-mix(in oklab, var(--color-red-500) 50%, transparent);
  }
}
```

`color-mix()` 形式在运行时仍可覆盖；它前面的静态回退值根据主题值计算，可供不支持 `color-mix()` 的浏览器使用。通过 `polyfills` 选项关闭回退：[`tw::compile()`](https://tailwindphp.inline0.dev/zh/docs/api#twcompile)。

### 叠加不透明度与 `color-mix()` → `oklab()`

不透明度修饰符可以叠加。对已有 50% 不透明度的值再应用 50%，结果就是 25%，并在 oklab 中计算。当不透明度修饰符针对静态颜色解析时，TailwindPHP 会将 `color-mix(in oklab, …)` 表达式折叠为具体的 `oklab()` 值——这与上游 Tailwind 工具链中 lightningcss 执行的转换相同；而动态颜色（仍由 `var()` 包裹的颜色）会保留 `color-mix()` 形式，因此仍可在运行时覆盖。

## 从 PHP 读取主题值

三个访问器会将解析后的主题值作为 PHP 数组返回。每个访问器都接受可选的输入 CSS 字符串（默认为 `@import "tailwindcss";`），也可通过 [compiler instance](https://tailwindphp.inline0.dev/zh/docs/api) 使用。

```php
use TailwindPHP\tw;

tw::colors();
// ['red-500' => 'oklch(63.7% .237 25.331)', 'blue-500' => 'oklch(62.3% .214 259.815)', ...]

tw::breakpoints();
// ['sm' => '40rem', 'md' => '48rem', 'lg' => '64rem', 'xl' => '80rem', '2xl' => '96rem']

tw::spacing('@import "tailwindcss"; @theme { --spacing-huge: 10rem; }');
// ['huge' => '10rem']
```

传入 CSS 字符串，即可根据自定义主题读取：

```php
tw::colors('@import "tailwindcss"; @theme { --color-brand: #3b82f6; }');
// [..., 'brand' => '#3b82f6']

tw::breakpoints('@import "tailwindcss"; @theme { --breakpoint-xs: 20rem; }');
// ['sm' => '40rem', ..., '2xl' => '96rem', 'xs' => '20rem']
```

TailwindCSS 4 使用单个 `--spacing` 基础值，而不是 `--spacing-*` 刻度，因此 `tw::spacing()` 只会返回你定义的自定义 `--spacing-*` 令牌。从编译器实例调用时也有相同的方法：`$compiler->colors()`、`$compiler->breakpoints()`、`$compiler->spacing()`。完整签名请参阅 [参考API](https://tailwindphp.inline0.dev/zh/docs/api)。

## 后续步骤

- [指令](https://tailwindphp.inline0.dev/zh/docs/usage/directives) — `@apply`、`@utility`、`@custom-variant`、`@layer`。
- [导入](https://tailwindphp.inline0.dev/zh/docs/usage/imports) — `@import`、虚拟模块和 Preflight。
- [API](https://tailwindphp.inline0.dev/zh/docs/api) — 所有访问器和检查方法。
