Skip to content
全部文档

在源文件中检测 class

理解并自定义 Tailwind 如何扫描源文件。

概述

Tailwind 的工作方式是扫描项目中的 utility class,然后根据你实际用到的 class 生成所需 CSS。

这样可以让 CSS 尽可能小,同时也让任意值 这类功能成为可能。

class 如何被检测

Tailwind 会把所有源文件当作纯文本处理,不会尝试以任何方式把文件当成代码去解析。

它只会根据 class 名中可能出现的字符,在文件里查找可能是 class 的 token:

JSX
jsx
// [!code word:bg-blue-500]
// [!code word:rounded-full]
// [!code word:text-white]
// [!code word:text-black]
// [!code word:font-medium]
// [!code word:text-sm\/6]
// [!code word:font-sans]
// [!code word:bg-black]
// [!code word:bg-white]
// [!code word:className]
// [!code word:function]
// [!code word:children]
// [!code word:button]
// [!code word:shadow]
// [!code word:export]
// [!code word:colors]
// [!code word:color]
// [!code word:black]
// [!code word:white]
// [!code word:const]
// [!code word:blue]
// [!code word:return]
// [!code word:py-1.5]
// [!code word:px-2]
export function Button({ color, children }) {
  const colors = {
    black: "bg-black text-white",
    blue: "bg-blue-500 text-white",
    white: "bg-white text-black",
  };

  return (
    <button className={`${colors[color]} rounded-full px-2 py-1.5 font-sans text-sm/6 font-medium shadow`}>
      {children}
    </button>
  );
}

然后它会尝试为这些 token 生成 CSS,并丢弃无法映射到框架已知 utility class 的 token。

动态 class 名

由于 Tailwind 把源文件当纯文本扫描,它无法理解你所用编程语言中的字符串拼接或插值。

DANGER

不要动态拼接 class 名

HTML
html
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>

上面的例子中并不存在 text-red-600text-green-600 这两个字符串,因此 Tailwind 不会生成这些 class。

相反,请确保你使用的 class 名都是完整出现的:

TIP

始终使用完整的 class 名

HTML
html
<!-- [!code word:text-red-600] -->
<!-- [!code word:text-green-600] -->
<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>

如果使用 React 或 Vue 这类组件库,这意味着你不应该用 props 动态拼接 class:

DANGER

不要用 props 动态构建 class 名

JSX
jsx
function Button({ color, children }) {
  return <button className={`bg-${color}-600 hover:bg-${color}-500 ...`}>{children}</button>;
}

相反,把 props 映射到在构建时就能静态检测到的完整 class 名:

TIP

始终把 props 映射到静态 class 名

JSX
jsx
function Button({ color, children }) {
  const colorVariants = {
    blue: "bg-blue-600 hover:bg-blue-500",
    red: "bg-red-600 hover:bg-red-500",
  };

  return <button className={`${colorVariants[color]} ...`}>{children}</button>;
}

这样做还有额外好处,例如可以把不同的 prop 值映射到不同的颜色色阶:

JSX
jsx
function Button({ color, children }) {
  const colorVariants = {
    blue: "bg-blue-600 hover:bg-blue-500 text-white",
    red: "bg-red-500 hover:bg-red-400 text-white",
    yellow: "bg-yellow-300 hover:bg-yellow-400 text-black",
  };

  return <button className={`${colorVariants[color]} ...`}>{children}</button>;
}

只要代码里始终使用完整的 class 名,Tailwind 每次都能正确生成全部 CSS。

会扫描哪些文件

Tailwind 会扫描项目中的每个文件以查找 class 名,但以下情况除外:

  • 位于 .gitignore 中的文件
  • node_modules 目录中的文件
  • 图片、视频、zip 等二进制文件
  • CSS 文件
  • 常见包管理器的 lock 文件

如果需要扫描 Tailwind 默认忽略的文件,可以显式注册 这些源。

显式注册源

使用 @source 显式注册相对于样式表的源路径:

CSS
css
@import "tailwindcss";
@source "../node_modules/@acmecorp/ui-lib";

这在需要扫描用 Tailwind 构建的外部库时特别有用,因为依赖通常写在 .gitignore 里,默认会被 Tailwind 忽略。

设置基础路径

默认情况下,Tailwind 以当前工作目录为起点扫描 class 名。

若要显式设置源检测的基础路径,在 CSS 中导入 Tailwind 时使用 source() 函数:

CSS
css
/* [!code word:source("../src")] */
@import "tailwindcss" source("../src");

在 monorepo 中,构建命令往往从仓库根目录而不是各个项目根目录运行,这时这个选项会很有用。

忽略特定路径

使用 @source not 在扫描 class 名时忽略相对于样式表的特定路径:

CSS
css
@import "tailwindcss";
@source not "../src/components/legacy";

如果项目中有很大的目录确定不会使用 Tailwind class(例如遗留组件或第三方库),这个功能会很有用。

禁用自动检测

如果你想显式注册全部源,可以使用 source(none) 彻底禁用自动源检测:

CSS
css
/* [!code word:source("../src")] */
@import "tailwindcss" source(none);

@source "../admin";
@source "../shared";

在包含多份 Tailwind 样式表的项目中,这可以确保每份样式表只包含各自需要的 class。

将特定 utility 加入 safelist

如果需要确保 Tailwind 生成内容文件中并不存在的某些 class 名,使用 @source inline() 强制生成它们:

CSS
css
@import "tailwindcss";
@source inline("underline");
Generated CSS
css
.underline {
  text-decoration-line: underline;
}

将变体加入 safelist

也可以用 @source inline() 生成带变体的 class。例如,要生成带 hoverfocus 变体的 underline class,在源输入中加上 {hover:,focus:,}

CSS
css
@import "tailwindcss";
@source inline("{hover:,focus:,}underline");
Generated CSS
css
.underline {
  text-decoration-line: underline;
}
@media (hover: hover) {
  .hover\:underline:hover {
    text-decoration-line: underline;
  }
}
@media (focus: focus) {
  .focus\:underline:focus {
    text-decoration-line: underline;
  }
}

使用范围加入 safelist

源输入会做花括号展开,因此可以一次生成多个 class。例如,要生成所有带 hover 变体的红色背景色,可以使用范围:

CSS
css
@import "tailwindcss";
@source inline("{hover:,}bg-red-{50,{100..900..100},950}");
Generated CSS
css
.bg-red-50 {
  background-color: var(--color-red-50);
}
.bg-red-100 {
  background-color: var(--color-red-100);
}
.bg-red-200 {
  background-color: var(--color-red-200);
}

/* ... */

.bg-red-800 {
  background-color: var(--color-red-800);
}
.bg-red-900 {
  background-color: var(--color-red-900);
}
.bg-red-950 {
  background-color: var(--color-red-950);
}
@media (hover: hover) {
  .hover\:bg-red-50:hover {
    background-color: var(--color-red-50);
  }

  /* ... */

  .hover\:bg-red-950:hover {
    background-color: var(--color-red-950);
  }
}

这会生成从 100 到 900、步长为 100 的红色背景色,再加上最浅的 50 和最深的 950。同时会为这些 class 各自加上 hover: 变体。

显式排除 class

使用 @source not inline() 可以阻止生成特定 class,即使它们出现在源文件中:

CSS
css
@import "tailwindcss";
@source not inline("{hover:,focus:,}bg-red-{50,{100..900..100},950}");

这会显式排除红色背景 utility 及其 hoverfocus 变体,不让它们被生成。

文档译文以 MIT 协议授权;原文版权归 Tailwind Labs。湘ICP备2026005453号-2