自定义
配置项目的源代码。
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 模式,这使得在不进行大量配置的情况下轻松匹配项目中的所有内容文件
*
匹配除斜杠和隐藏文件之外的任何内容**
匹配零个或多个目录{}
之间使用逗号分隔值以匹配一组选项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 等组件库,这意味着你不应该使用道具动态构建类
不要使用道具动态构建类名
function Button({ color, children }) {
return (
<button className={`bg-${color}-600 hover:bg-${color}-500 ...`}>
{children}
</button>
)
}
相反,将道具映射到在构建时可以静态检测到的完整类名
始终将道具映射到静态类名
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>
)
}
这具有额外的优点,例如允许你将不同的道具值映射到不同的颜色阴影
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。
如果您正在使用具有工作空间的单一仓库,您可能需要使用 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' },
],
// ...
}
这没有很多有效的用例——安全列出通常是您真正想要的。
为了获得最小的文件大小和最佳的开发体验,我们强烈建议依靠你的 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>
您可能还想防止 Tailwind 在这些类与某些现有 CSS 冲突时生成某些类,但您不想对所有 Tailwind 类进行前缀。
在这些情况下,您可以使用 blocklist
选项告诉 Tailwind 忽略它在您的内容中检测到的特定类
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
blocklist: [
'container',
'collapse',
],
// ...
}
blocklist
选项仅影响 Tailwind 生成的 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>
阅读我们关于 动态类名 的文档以了解更多详细信息。
如果您的 CSS 似乎在无限循环中重建,很可能是因为您的构建工具在 注册 PostCSS 依赖项 时不支持 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}',
],
// ...
}
因此,如果您正在监视 src/**/*.html
的更改,但将 CSS 输出文件写入 src/css/styles.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",
},
}