
# 指令

指令是你在输入 CSS 中编写的、以 `@` 为前缀的 at-rule，用于组合、扩展并控制 Tailwind 的输出。本页介绍 `@apply`、`@utility`、`@variant`、`@custom-variant` 和 `@layer`。`@theme` 详见 [主题](https://tailwindphp.inline0.dev/zh/docs/usage/theme)；`@plugin` 详见 [插件](https://tailwindphp.inline0.dev/zh/docs/plugins)；`@source` 详见 [@source](https://tailwindphp.inline0.dev/zh/docs/usage/source)。

## `@apply`

`@apply` 会将现有工具类的声明内联到你自己的选择器中。你可以用它将工具类样式附加到语义化类中，包括嵌套选择器和媒体查询内部。

```php
use TailwindPHP\tw;

$css = tw::generate('<div class="btn">', '
    @import "tailwindcss";

    @theme { --color-brand: #3b82f6; }

    .btn {
        @apply px-4 py-2 rounded-lg bg-brand text-white;
    }
');
```

变体可以放在 `@apply` 列表中——`@apply bg-blue-500 hover:bg-blue-600;` 会展开 `:hover` 状态，`@apply px-4 md:px-6 lg:px-8;` 这样的响应式前缀则会生成相应的 `@media` 规则。重要修饰符也同样有效（`@apply !flex;`）。同时支持嵌套选择器，因此类似 `.card { h2 { @apply text-xl font-bold; } }` 的规则会将工具类应用于嵌套的 `h2`。

`@apply` 是一条语句：`@apply px-4 { … }` 带有主体时会报错。只列出带连字符标识符（`@apply --my-mixin;`）的 `@apply`，是 [CSS mixins 草案](https://drafts.csswg.org/css-mixins-1/#apply-rule)中的 CSS 混入，而非工具类列表，因此 TailwindPHP 无法解析它；在同一个 `@apply` 中混用混入和工具类也会报错（`You cannot use @apply with both mixins and utilities…`）。目前，混入规则会从输出中丢弃，而不会原样传递（[#12](https://github.com/inline0/tailwindphp/issues/12)）。

## `@utility`

`@utility` 会注册一个自定义工具类，使其参与 Tailwind 的引擎处理——它会被排序到 `utilities` 层，并且像内置工具类一样支持变体。静态工具类采用固定的主体：

```css
@utility content-auto {
    content-visibility: auto;
}
```

由于它是一个真正的工具类，变体会自动组合（`hover:content-auto`、`md:content-auto`）。主体本身也可以使用 `@apply` 和嵌套选择器：

```css
@utility btn-primary {
    @apply px-4 py-2 bg-blue-500 text-white rounded;
}

@utility card {
    color: red;
    &:hover { color: blue; }
}
```

函数式工具类的名称使用 `-*` 后缀，并通过 `--value()` 读取匹配到的值：

```css
@theme {
    --gutter-wide: 3rem;
}

@utility gutter-* {
    padding-inline: --value(--gutter-*, [length]);
    padding-inline: --spacing(--value(integer));
}
```

`--value()` 会依次尝试使用各来源解析候选项的值：主题命名空间（`--gutter-*`）、带数据类型的任意值（`[length]`），或未指定类型的值（`integer`、`number`、`percentage`、`ratio`）。无法解析其 `--value()` 的声明会被丢弃，因此可以叠加多个声明作为回退链：

| 类名 | 输出 |
|---|---|
| `gutter-wide` | `padding-inline: var(--gutter-wide);` |
| `gutter-[5px]` | `padding-inline: 5px;` |
| `gutter-4` | `padding-inline: calc(var(--spacing) * 4);` |

`--modifier()` 对 `/` 之后部分的解析方式相同：主体中包含 `line-height: --modifier(integer);` 时，`gutter-4/7` 也会生成 `line-height: 7`。工具类名称遵循 TailwindCSS v4.3.3 规则：最多一个 `/`，`%` 只能在末尾且前面必须是数字，小数点只能出现在数字之间。

## `@variant`

`@variant` 会将变体应用于你自己的 CSS 内部声明，而无需定义工具类：

```css
.card {
    color: red;

    @variant hover {
        color: blue;
    }

    @variant dark {
        color: white;
    }
}
```

```css
.card {
  color: red;
}
@media (hover: hover) {
  .card:hover {
    color: #00f;
  }
}
@media (prefers-color-scheme: dark) {
  .card {
    color: #fff;
  }
}
```

变体可以叠加（`@variant hover:focus`）、用逗号列出、相互嵌套，也可以指定你自己的 `@custom-variant`。为保持向后兼容，顶层 `@variant` 没有主体或带有 `@slot` 时，会被视为 `@custom-variant`。

## `@custom-variant`

`@custom-variant` 会定义一个新变体，你可以将它作为前缀加到任意工具类上。简写形式会命名变体，并在括号中指定选择器或 at-rule。

选择器列表变体使用 `&` 代表该元素：

```css
@custom-variant hocus (&:hover, &:focus);
```

`hocus:bg-blue-500` 随后会同时生成 `:hover` 和 `:focus` 规则。属性形式的写法也相同：

```css
@custom-variant loading (&[data-loading="true"]);
```

at-rule 变体会将匹配的工具类包裹在该 at-rule 中：

```css
@custom-variant tablet (@media (min-width: 600px));
```

自定义变体可以与内置变体叠加——`sm:hocus:bg-blue-500` 会将 `hocus` 选择器嵌套在 `sm` 媒体查询中。更复杂的情况可以使用块形式，并用 `@slot` 标记工具类声明的注入位置：

```css
@custom-variant child {
    & > * {
        @slot;
    }
}

@custom-variant sidebar-open {
    .sidebar-open & {
        @slot;
    }
}
```

## `@layer`

`@layer` 使用原生的 CSS 层来控制层叠顺序。单独的 `@layer` 语句会声明各层的顺序；无论选择器的优先级如何，后面的层都优先。Tailwind 的标准顺序为：

```css
@layer theme, base, components, utilities;
```

这正是 `@import "tailwindcss"` 在内部设置的顺序。你可以声明自己的顺序，也可以拆分成多条语句（先写 `@layer reset, base;`，再写 `@layer components, utilities;`），还可以通过块将规则分配到指定层：

```php
use TailwindPHP\tw;

$css = tw::generate('<article><h1>Title</h1></article>', '
    @import "tailwindcss";

    @layer base {
        h1 { font-size: var(--text-2xl); }
        a  { color: var(--color-blue-600); text-decoration-line: underline; }
    }
');
```

通过 `@layer base` 添加基础样式，可以让它们排在 `components` 和 `utilities` 之下，因此工具类始终会覆盖元素的默认样式。`@layer components { … }` 也适用相同原则，可用于将组件类置于工具类之下。匿名层和 `@import` 上的 `layer()` 修饰符详见 [导入](https://tailwindphp.inline0.dev/zh/docs/usage/imports)。

## 后续步骤

- [主题](https://tailwindphp.inline0.dev/zh/docs/usage/theme) — `@theme` 设计令牌和主题函数。
- [导入](https://tailwindphp.inline0.dev/zh/docs/usage/imports) — `@import`、虚拟模块和 `layer()` 修饰符。
- [插件](https://tailwindphp.inline0.dev/zh/docs/plugins) — `@plugin` 指令和插件 API。
- [@source](https://tailwindphp.inline0.dev/zh/docs/usage/source) — 控制要扫描哪些文件和类名。
