定制
为您的项目配置内容源。
tailwind.config.js
文件的 content
部分用于配置所有 HTML 模板、JavaScript 组件以及任何其他包含 Tailwind 类名的源文件的路径。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
// ...
}
本指南涵盖了您需要了解的所有内容,以确保 Tailwind 生成项目所需的所有 CSS。
Tailwind CSS 的工作原理是扫描所有 HTML、JavaScript 组件和任何其他模板文件中的类名,然后为这些样式生成所有相应的 CSS。
为了让 Tailwind 生成您需要的所有 CSS,它需要了解项目中包含任何 Tailwind 类名的每个文件。
在配置文件的 content
部分中配置所有内容文件的路径:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}'
],
// ...
}
路径配置为glob patterns,可以轻松匹配项目中的所有内容文件,而无需大量配置:
*
匹配除斜杠和隐藏文件之外的任何内容**
匹配零个或多个目录{}
之间的逗号分隔值来匹配选项列表Tailwind 在底层使用了 fast-glob 库 — — 请查看其文档以了解其他支持的模式功能。
路径是相对于您的项目根目录的,而不是您的 tailwind.config.js
文件,因此如果您的 tailwind.config.js
文件位于自定义位置,您仍应相对于项目根目录编写路径。
为了获得最佳性能并避免误报,请尽可能具体地配置您的内容。
如果你使用像这样的非常广泛的模式,Tailwind 甚至会扫描 node_modules
来查找可能不是你想要的内容:
不要使用过于宽泛的模式
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./**/*.{html,js}',
],
// ...
}
如果您需要扫描项目根目录中的任何文件(通常是 index.html
文件),请单独列出该文件,以便您的其他模式可以更加具体:
具体说明您的内容模式
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./components/**/*.{html,js}',
'./pages/**/*.{html,js}',
'./index.html',
],
// ...
}
一些框架将其主 HTML 入口点隐藏在与其余模板不同的地方(通常为 public/index.html
),因此如果您要将 Tailwind 类添加到该文件,请确保它也包含在您的配置中:
请记得包含您的 HTML 入口点(如适用)
module.exports = {
content: [
'./public/index.html',
'./src/**/*.{html,js}',
],
// ...
}
如果您有任何操纵 HTML 来添加类的 JavaScript 文件,请确保也包含这些文件:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
// ...
'./src/**/*.js',
],
// ...
}
// ...
menuButton.addEventListener('click', function () {
let classList = document.getElementById('nav').classList
classList.toggle('hidden')
classList.toggle('block')
})
// ...
同样重要的是不要扫描任何 CSS 文件 - 配置 Tailwind 来扫描使用类名的 模板,而不是 Tailwind 正在生成的 CSS 文件。
切勿在内容配置中包含 CSS 文件
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./src/**/*.css',
],
// ...
}
Tailwind 扫描源代码中类的方式非常简单 - 我们实际上并不会以编写语言来解析或执行任何代码,我们只是使用正则表达式来提取可能是类名的每个字符串。
例如,这里有一些 HTML,其中每个潜在的类名字符串都单独突出显示:
<div class="md:flex">
<div class="md:flex-shrink-0">
<img class="rounded-lg md:w-56" src="/img/shopping.jpg" alt="Woman paying for a purchase">
</div>
<div class="mt-4 md:mt-0 md:ml-6">
<div class="uppercase tracking-wide text-sm text-indigo-600 font-bold">
Marketing
</div>
<a href="/get-started" class="block mt-1 text-lg leading-tight font-semibold text-gray-900 hover:underline">
Finding customers for your new business
</a>
<p class="mt-2 text-gray-600">
Getting a new business off the ground is a lot of hard work.
Here are five ideas you can use to find your first customers.
</p>
</div>
</div>
我们不只将搜索范围限制在 class="..."
属性上,因为您可以在任何地方使用类,例如在某些 JavaScript 中用于切换菜单:
<script>
menuButton.addEventListener('click', function () {
let classList = document.getElementById('nav').classList
classList.toggle('hidden')
classList.toggle('block')
})
</script>
通过使用这种非常简单的方法,Tailwind 可以非常可靠地与任何编程语言配合使用,例如 JSX:
const sizes = {
md: 'px-4 py-2 rounded-md text-base',
lg: 'px-5 py-3 rounded-lg text-lg',
}
const colors = {
indigo: 'bg-indigo-500 hover:bg-indigo-600 text-white',
cyan: 'bg-cyan-600 hover:bg-cyan-700 text-white',
}
export default function Button({ color, size, children }) {
let colorClasses = colors[color]
let sizeClasses = sizes[size]
return (
<button type="button" className={`font-bold ${sizeClasses} ${colorClasses}`}>
{children}
</button>
)
}
Tailwind 提取类名的方式最重要的含义是,它只会在源文件中找到以完整的不间断字符串形式存在的类。
如果你使用字符串插值或将部分类名连接在一起,Tailwind 将找不到它们,因此不会生成相应的 CSS:
不要动态构造类名
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
在上面的例子中,字符串 text-red-600
和 text-green-600
不存在,因此 Tailwind 不会生成这些类。
相反,请确保您使用的任何类名都完整存在:
始终使用完整的类名
<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
如果您正在使用 React 或 Vue 之类的组件库,这意味着您不应该使用 props 来动态构造类:
不要使用 props 动态构建类名
function Button({ color, children }) {
return (
<button className={`bg-${color}-600 hover:bg-${color}-500 ...`}>
{children}
</button>
)
}
相反,将 props 映射到在构建时可静态检测的完整类名:
始终将 props 映射到静态类名
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 值映射到不同的颜色色调,例如:
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>
)
}
只要您在代码中始终使用完整的类名,Tailwind 每次都会完美地生成您的所有 CSS。
如果您正在使用任何第三方库(例如 Select2)并使用您自己的自定义 CSS 设置该库的样式,我们建议您在不使用 Tailwind 的 @layer
功能的情况下编写这些样式:
@tailwind base;
@tailwind components;
.select2-dropdown {
@apply rounded-b-lg shadow-md;
}
.select2-search {
@apply border border-gray-300 rounded;
}
.select2-results__group {
@apply text-lg font-bold text-gray-900;
}
/* ... */
@tailwind utilities;
这将确保 Tailwind 始终在你的 CSS 中包含这些样式,这比配置 Tailwind 来扫描第三方库的源代码要容易得多。
如果您已经创建了自己的可重用组件集,并使用 Tailwind 设置其样式,并将其导入到多个项目中,请确保配置 Tailwind 以扫描这些组件中的类名:
module.exports = {
content: [
'./components/**/*.{html,js}',
'./pages/**/*.{html,js}',
'./node_modules/@my-company/tailwind-components/**/*.js',
],
// ...
}
这将确保 Tailwind 生成这些组件所需的所有 CSS。
如果您在具有工作区的 monorepo 中工作,则可能需要使用 require.resolve
来确保 Tailwind 可以看到您的内容文件:
const path = require('path');
module.exports = {
content: [
'./components/**/*.{html,js}',
'./pages/**/*.{html,js}',
path.join(path.dirname(require.resolve('@my-company/tailwind-components')), '**/*.js'),
],
// ...
}
默认情况下,Tailwind 解析相对于当前工作目录(而不是 tailwind.config.js
文件)的非绝对内容路径。如果您从其他目录运行 Tailwind,这可能会导致意外结果。
要始终解析相对于 tailwind.config.js
文件的路径,请使用对象表示法表示 content
配置,并将 relative
属性设置为 true
:
module.exports = {
content: {
relative: true,
files: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
},
// ...
}
这很可能成为框架下一个主要版本中的默认行为。
如果出于某种原因你需要配置 Tailwind 来扫描某些原始内容而不是文件内容,请使用带有 raw
键的对象而不是路径:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
{ raw: '<div class="font-bold">', extension: 'html' },
],
// ...
}
对于这种情况,没有太多有效的用例——safelisting 通常是你真正想要的。
为了获得最小的文件大小和最佳的开发体验,我们强烈建议您依靠 content
配置来告诉 Tailwind 尽可能多地生成哪些类。
安全列表是最后的手段,仅应在无法扫描特定内容以查找类名的情况下使用。这种情况很少见,您几乎永远不需要此功能。
如果您需要确保 Tailwind 生成内容文件中不存在的某些类名,请使用 safelist
选项:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
safelist: [
'bg-red-500',
'text-3xl',
'lg:text-4xl',
]
// ...
}
一个很有用的例子是,如果您的网站显示用户生成的内容,并且您希望用户能够在其内容中使用一组受限的 Tailwind 类,而这些类可能不存在于您自己网站的源文件中。
Tailwind 支持基于模式的安全列表,适用于需要将大量类列入安全列表的情况:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
safelist: [
'text-2xl',
'text-3xl',
{
pattern: /bg-(red|green|blue)-(100|200|300)/,
},
],
// ...
}
模式只能与基本实用程序名称(如 /bg-red-.+/
)匹配,如果模式包含变体修饰符(如 /hover:bg-red-.+/
),则不会匹配。
如果您想强制 Tailwind 为任何匹配的类生成变体,请使用 variants
选项将它们包含在内:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
safelist: [
'text-2xl',
'text-3xl',
{
pattern: /bg-(red|green|blue)-(100|200|300)/,
variants: ['lg', 'hover', 'focus', 'lg:hover'],
},
],
// ...
}
由于 Tailwind 使用一种非常简单的方法来检测内容中的类名,您可能会发现生成了一些您实际上不需要的类。
例如,即使该类实际上并未被使用,此 HTML 仍会生成 container
类:
<div class="text-lg leading-8 text-gray-600">
Every custom pool we design starts as a used shipping container, and is
retrofitted with state of the art technology and finishes to turn it into
a beautiful and functional way to entertain your guests all summer long.
</div>
当这些类与某些现有 CSS 冲突时,您可能还希望阻止 Tailwind 生成某些类,但您不想在所有 Tailwind 类中添加前缀。
在这些情况下,您可以使用 blocklist
选项来告诉 Tailwind 忽略它在您的内容中检测到的特定类:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
blocklist: [
'container',
'collapse',
],
// ...
}
blocklist
选项仅影响 Tailwind 生成的 CSS,而不会影响您自己编写的自定义 CSS 或从其他库导入的 CSS。
与 safelist
不同,blocklist
选项仅支持字符串,并且您不能使用正则表达式阻止类。
如果您以可编译为 HTML 的格式(如 Markdown)创作内容,则在扫描类名之前将该内容编译为 HTML 通常是有意义的。
在提取类之前,使用 content.transform
选项转换与特定文件扩展名匹配的任何内容:
const remark = require('remark')
module.exports = {
content: {
files: ['./src/**/*.{html,md}'],
transform: {
md: (content) => {
return remark().process(content)
}
}
},
// ...
}
当使用 content.transform
时,您需要使用 content.files
而不是作为 content
下的顶级数组来提供源路径。
使用 extract
选项来覆盖 Tailwind 用于检测特定文件扩展名的类名的逻辑:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: {
files: ['./src/**/*.{html,wtf}'],
extract: {
wtf: (content) => {
return content.match(/[^<>"'`\s]*/g)
}
}
},
// ...
}
这是一个高级功能,大多数用户不需要它——Tailwind 中的默认提取逻辑对于几乎所有项目都非常有效。
与转换一样,当使用 content.extract
时,您需要使用 content.files
而不是作为 content
下的顶级数组来提供源路径。
如果 Tailwind 没有生成类,请确保您的 content
配置正确且匹配所有正确的源文件。
一个常见的错误是缺少文件扩展名,例如如果你在 React 组件中使用 jsx
而不是 js
:
module.exports = {
content: [
'./src/**/*.{html,js}',
'./src/**/*.{html,js,jsx}'
],
// ...
}
或者在项目中期创建一个最初未涵盖的新文件夹并忘记将其添加到您的配置中:
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
'./util/**/*.{html,js}'
],
// ...
}
也可能是您正在尝试使用动态类名,但这并不适用,因为 Tailwind 实际上并不会评估您的源代码,而且只能检测静态的未中断的类字符串。
不要动态构造类名
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
确保在代码中始终使用完整的类名:
始终使用完整的类名
<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
阅读有关 dynamic class names 的文档以了解更多详细信息。
如果您的 CSS 似乎在无限循环中重建,很有可能是因为您的构建工具在 registering PostCSS dependencies 时不支持 glob
选项。
许多构建工具(例如 webpack)不支持此选项,因此我们只能告诉它们监视特定文件或_整个目录_。例如,我们不能告诉 webpack _仅_监视目录中的 *.html
个文件。
这意味着如果构建 CSS 导致这些目录中的任何文件发生变化,就会触发重建,即使更改的文件与 glob 中的扩展名不匹配。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
// With some build tools, your CSS will rebuild
// any time *any* file in `src` changes.
'./src/**/*.{html,js}',
],
// ...
}
因此,如果您正在观察 的变化,但又将 CSS 输出文件写入 ,则使用某些工具时会陷入无限重建循环。
理想情况下,我们可以在控制台中就此发出警告,但许多工具都完全支持它(包括我们自己的 CLI 工具),并且我们没有可靠的方法来检测您正在使用的构建工具。
为了解决这个问题,请在 content
配置中使用更具体的路径,确保仅包含在 CSS 构建时不会改变的目录:
module.exports = {
content: [
'./src/**/*.{html,js}',
'./src/pages/**/*.{html,js}',
'./src/components/**/*.{html,js}',
'./src/layouts/**/*.{html,js}',
'./src/index.html',
],
// ...
}
如果有必要,请调整您的实际项目目录结构,以确保您可以定位您的模板文件,而不会意外捕获您的 CSS 文件或其他构建工件(如清单文件)。
如果您绝对无法更改内容配置或目录结构,最好的办法是使用具有完整 glob 支持的工具单独编译 CSS。我们建议使用 Tailwind CLI,它是一种快速、简单、专门构建的工具,用于使用 Tailwind 编译 CSS。
如果您遇到了奇怪的、难以描述的输出问题,或者事情似乎根本不起作用,那么很有可能是因为您的构建工具没有正确支持 PostCSS 依赖项消息(或根本不支持)。目前已知的一个示例是 Stencil。
当您遇到此类问题时,我们建议使用 Tailwind CLI 单独编译您的 CSS,而不是尝试将 Tailwind 集成到您现有的工具中。
您可以使用 npm-run-all
或 concurrently
之类的包来编译您的 CSS,同时使用您常用的开发命令,方法是向您的项目添加一些脚本,如下所示:
// package.json
{
// ...
"scripts": {
"start": "concurrently \"npm run start:css\" \"react-scripts start\"",
"start:css": "tailwindcss -o src/tailwind.css --watch",
"build": "npm run build:css && react-scripts build",
"build:css": "NODE_ENV=production tailwindcss -o src/tailwind.css -m",
},
}
无论如何,请务必输入 check for an existing issue 或 open a new one,以便我们找出问题所在,并尝试提高与您所使用的工具的兼容性。