
核心概念
将你自己的自定义样式添加到 Tailwind 的最佳实践。
在使用框架时,最大的挑战往往是弄清楚当你需要某些框架没有为你处理的东西时,你应该做什么。
🌐 Often the biggest challenge when working with a framework is figuring out what you’re supposed to do when there’s something you need that the framework doesn’t handle for you.
Tailwind 从零开始就被设计成可扩展和可定制的,因此无论你在构建什么,都不会觉得是在与框架作斗争。
🌐 Tailwind has been designed from the ground up to be extensible and customizable, so that no matter what you’re building you never feel like you’re fighting the framework.
本指南涵盖的主题包括自定义你的设计标记、如何在必要时打破这些限制、添加你自己的自定义 CSS 以及使用插件扩展框架。
🌐 This guide covers topics like customizing your design tokens, how to break out of those constraints when necessary, adding your own custom CSS, and extending the framework with plugins.
如果你想更改颜色调色板、间距比例、排版比例或断点等内容,请将你的自定义设置添加到 tailwind.config.js 文件的 theme 部分:
🌐 If you want to change things like your color palette, spacing scale, typography scale, or breakpoints, add your customizations to the theme section of your tailwind.config.js file:
/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
screens: {
sm: '480px',
md: '768px',
lg: '976px',
xl: '1440px',
},
colors: {
'blue': '#1fb6ff',
'pink': '#ff49db',
'orange': '#ff7849',
'green': '#13ce66',
'gray-dark': '#273444',
'gray': '#8492a6',
'gray-light': '#d3dce6',
},
fontFamily: {
sans: ['Graphik', 'sans-serif'],
serif: ['Merriweather', 'serif'],
},
extend: {
spacing: {
'128': '32rem',
'144': '36rem',
},
borderRadius: {
'4xl': '2rem',
}
}
}
}在 主题配置 文档中了解有关自定义主题的更多信息。
🌐 Learn more about customizing your theme in the Theme Configuration documentation.
虽然你通常可以使用一组受限的设计标记来构建大量精心设计的设计,但有时你需要突破这些限制以获得像素完美的东西。
🌐 While you can usually build the bulk of a well-crafted design using a constrained set of design tokens, once in a while you need to break out of those constraints to get things pixel-perfect.
当你发现在某个特定位置准确获取背景图片时,真的需要像 top: 117px 这样的东西时,可以使用 Tailwind 的方括号表示法,随时生成具有任意值的类:
🌐 When you find yourself really needing something like top: 117px to get a background image in just the right spot, use Tailwind’s square bracket notation to generate a class on the fly with any arbitrary value:
<div class="top-[117px]">
<!-- ... -->
</div>
这基本上就像内联样式,主要的好处是你可以将其与交互式修饰符(如 hover)和响应式修饰符(如 lg)结合使用:
🌐 This is basically like inline styles, with the major benefit that you can combine it with interactive modifiers like hover and responsive modifiers like lg:
<div class="top-[117px] lg:top-[344px]">
<!-- ... -->
</div>
这适用于框架中的所有内容,包括背景颜色、字体大小、伪元素内容等:
🌐 This works for everything in the framework, including things like background colors, font sizes, pseudo-element content, and more:
<div class="bg-[#bada55] text-[22px] before:content-['Festivus']">
<!-- ... -->
</div>
甚至可以使用theme 函数来引用你在 tailwind.config.js 文件中的设计令牌:
🌐 It’s even possible to use the theme function to reference the design tokens in your tailwind.config.js file:
<div class="grid grid-cols-[fit-content(theme(spacing.32))]">
<!-- ... -->
</div>
在将 CSS 变量用作任意值时,不需要将变量用 var(...) 封装——只需提供实际的变量名即可:
🌐 When using a CSS variable as an arbitrary value, wrapping your variable in var(...) isn’t needed — just providing the actual variable name is enough:
<div class="bg-[--my-color]">
<!-- ... -->
</div>
如果你需要使用 Tailwind 不包含开箱即用工具的 CSS 属性,你还可以使用方括号表示法来编写完全任意的 CSS:
🌐 If you ever need to use a CSS property that Tailwind doesn’t include a utility for out of the box, you can also use square bracket notation to write completely arbitrary CSS:
<div class="[mask-type:luminance]">
<!-- ... -->
</div>
这真的很像内联样式,但同样有一个好处,就是你可以使用修饰符:
🌐 This is really like inline styles, but again with the benefit that you can use modifiers:
<div class="[mask-type:luminance] hover:[mask-type:alpha]">
<!-- ... -->
</div>
这对于 CSS 变量之类的东西也很有用,尤其是当它们需要在不同条件下更改时:
🌐 This can be useful for things like CSS variables as well, especially when they need to change under different conditions:
<div class="[--scroll-offset:56px] lg:[--scroll-offset:44px]">
<!-- ... -->
</div>
任意 variants 就像任意值一样,但用于即时修改选择器,就像你可以使用内置的伪类 variants(例如 hover:{utility})或响应式 variants(例如 md:{utility})一样,只不过是直接在 HTML 中使用方括号表示法。
🌐 Arbitrary variants are like arbitrary values but for doing on-the-fly selector modification, like you can with built-in pseudo-class variants like hover:{utility} or responsive variants like md:{utility} but using square bracket notation directly in your HTML.
<ul role="list">
{#each items as item}
<li class="lg:[&:nth-child(3)]:hover:underline">{item}</li>
{/each}
</ul>在任意变体文档中了解更多信息。
🌐 Learn more in the arbitrary variants documentation.
当任意值需要包含空格时,可以使用下划线(_)代替,Tailwind 会在构建时自动将其转换为空格:
🌐 When an arbitrary value needs to contain a space, use an underscore (_) instead and Tailwind will automatically convert it to a space at build-time:
<div class="grid grid-cols-[1fr_500px_2fr]">
<!-- ... -->
</div>
在下划线很常见但空格无效的情况下,Tailwind 将保留下划线而不是将其转换为空格,例如在 URL 中:
🌐 In situations where underscores are common but spaces are invalid, Tailwind will preserve the underscore instead of converting it to a space, for example in URLs:
<div class="bg-[url('/what_a_rush.png')]">
<!-- ... -->
</div>
在极少数情况下,你实际上需要使用下划线,但由于空格也有效而导致歧义,请使用反斜杠转义下划线,Tailwind 不会将其转换为空格:
🌐 In the rare case that you actually need to use an underscore but it’s ambiguous because a space is valid as well, escape the underscore with a backslash and Tailwind won’t convert it to a space:
<div class="before:content-['hello\_world']">
<!-- ... -->
</div>
如果你使用类似 JSX 这样的东西,其中反斜杠会在渲染的 HTML 中被去掉,请使用 String.raw(),这样反斜杠就不会被当作 JavaScript 的转义字符处理:
🌐 If you’re using something like JSX where the backslash is stripped from the rendered HTML, use String.raw() so the backslash isn’t treated as a JavaScript escape character:
<div className={String.raw`before:content-['hello\_world']`}>
<!-- ... -->
</div>
Tailwind 中的许多工具类共享一个公共命名空间,但映射到不同的 CSS 属性。例如,text-lg 和 text-black 都共享 text- 命名空间,但一个用于 font-size,另一个用于 color。
🌐 Many utilities in Tailwind share a common namespace but map to different CSS properties. For example text-lg and text-black both share the text- namespace, but one is for font-size and the other is for color.
使用任意值时,Tailwind 通常可以根据你传入的值自动处理这种歧义:
🌐 When using arbitrary values, Tailwind can generally handle this ambiguity automatically based on the value you pass in:
<!-- Will generate a font-size utility -->
<div class="text-[22px]">...</div>
<!-- Will generate a color utility -->
<div class="text-[#bada55]">...</div>
有时它确实是模棱两可的,例如在使用 CSS 变量时:
🌐 Sometimes it really is ambiguous though, for example when using CSS variables:
<div class="text-[var(--my-var)]">...</div>
在这些情况下,你可以通过在值前添加 CSS 数据类型 来向 Tailwind “提示”底层类型:
🌐 In these situations, you can “hint” the underlying type to Tailwind by adding a CSS data type before the value:
<!-- Will generate a font-size utility -->
<div class="text-[length:var(--my-var)]">...</div>
<!-- Will generate a color utility -->
<div class="text-[color:var(--my-var)]">...</div>
当你需要向 Tailwind 项目添加真正自定义的 CSS 规则时,最简单的方法就是将自定义 CSS 添加到你的样式表中:
🌐 When you need to add truly custom CSS rules to a Tailwind project, the easiest approach is to just add the custom CSS to your stylesheet:
@tailwind base;
@tailwind components;
@tailwind utilities;
.my-custom-style {
/* ... */
}为了获得更强的功能,你也可以使用 @layer 指令向 Tailwind 的 base、components 和 utilities 层添加样式:
🌐 For more power, you can also use the @layer directive to add styles to Tailwind’s base, components, and utilities layers:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.my-custom-style {
/* ... */
}
}在 CSS 中,当两个选择器的优先级相同时,样式表中规则的顺序决定了哪个声明会生效:
🌐 In CSS, the order of the rules in your stylesheet decides which declaration wins when two selectors have the same specificity:
.btn {
background: blue;
/* ... */
}
.bg-black {
background: black;
}在这里,两个按钮都会是黑色的,因为 .bg-black 在 CSS 中位于 .btn 之后:
🌐 Here, both buttons will be black since .bg-black comes after .btn in the CSS:
<button class="btn bg-black">...</button>
<button class="bg-black btn">...</button>为了管理这一点,Tailwind 将其生成的样式组织成三个不同的“层”——这一概念由 ITCSS 推广。
🌐 To manage this, Tailwind organizes the styles it generates into three different “layers” — a concept popularized by ITCSS.
base 层用于诸如重置规则或应用于普通 HTML 元素的默认样式之类的内容。components 层用于基于类的样式,你可以通过实用工具来覆盖这些样式。utilities 层用于小型、单一用途的类,这些类应始终优先于其他任何样式。明确说明这一点可以更容易地理解你的样式如何相互作用,而使用 @layer 指令可以让你控制最终的声明顺序,同时仍然可以按照你喜欢的方式组织实际的代码。
🌐 Being explicit about this makes it easier to understand how your styles will interact with each other, and using the @layer directive lets you control the final declaration order while still organizing your actual code in whatever way you like.
@layer 指令可以帮助你通过自动将样式重新定位到对应的 @tailwind 指令来控制声明顺序,还能为你自定义的 CSS 启用类似 修饰符 和 树摇 的功能。
🌐 The @layer directive helps you control declaration order by automatically relocating your styles to the corresponding @tailwind directive, and also enables features like modifiers and tree-shaking for your own custom CSS.
如果你只是想为页面设置一些默认值(例如文本颜色、背景颜色或字体系列),最简单的办法就是在 html 或 body 元素上添加一些类:
🌐 If you just want to set some defaults for the page (like the text color, background color, or font family), the easiest option is just adding some classes to the html or body elements:
<!doctype html>
<html lang="en" class="text-gray-900 bg-gray-100 font-serif">
<!-- ... -->
</html>
这会将你的基本样式决策与所有其他样式一起保存在标记中,而不是将它们隐藏在单独的文件中。
🌐 This keeps your base styling decisions in your markup alongside all of your other styles, instead of hiding them in a separate file.
如果你想为特定的 HTML 元素添加自己的默认基础样式,可以使用 @layer 指令将这些样式添加到 Tailwind 的 base 层:
🌐 If you want to add your own default base styles for specific HTML elements, use the @layer directive to add those styles to Tailwind’s base layer:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
h1 {
@apply text-2xl;
}
h2 {
@apply text-xl;
}
/* ... */
}在添加自定义基础样式时,如果你想引用在你的主题中定义的任何值,请使用 theme 函数或 @apply 指令。
🌐 Use the theme function or @apply directive when adding custom base styles if you want to refer to any of the values defined in your theme.
对于你想在项目中添加的任何更复杂的类,如果你仍希望能够使用实用类进行覆盖,请使用 components 层。
🌐 Use the components layer for any more complicated classes you want to add to your project that you’d still like to be able to override with utility classes.
传统上,这些会是像 card、btn、badge 这样的类——类似这样的东西。
🌐 Traditionally these would be classes like card, btn, badge — that kind of thing.
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.card {
background-color: theme('colors.white');
border-radius: theme('borderRadius.lg');
padding: theme('spacing.6');
box-shadow: theme('boxShadow.xl');
}
/* ... */
}通过在 components 层定义组件类,你仍然可以在必要时使用工具类来覆盖它们:
🌐 By defining component classes in the components layer, you can still use utility classes to override them when necessary:
<!-- Will look like a card, but with square corners -->
<div class="card rounded-none">
<!-- ... -->
</div>
使用 Tailwind 时,你可能不会像想象中那样经常需要这些类型的类。请阅读我们的样式重用指南了解我们的建议。
🌐 Using Tailwind you probably don’t need these types of classes as often as you think. Read our guide on Reusing Styles for our recommendations.
components 层也是放置你正在使用的任何第三方组件自定义样式的好地方:
🌐 The components layer is also a good place to put custom styles for any third-party components you’re using:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer 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;
}
/* ... */
}在添加自定义组件样式时,如果你想引用在你的主题中定义的任何值,请使用 theme 函数或 @apply 指令。
🌐 Use the theme function or @apply directive when adding custom component styles if you want to refer to any of the values defined in your theme.
将你自己的任何自定义实用程序类添加到 Tailwind 的 utilities 层:
🌐 Add any of your own custom utility classes to Tailwind’s utilities layer:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
.content-auto {
content-visibility: auto;
}
}当你的项目中有某个 CSS 功能想使用,而 Tailwind 默认没有提供对应的工具类时,这会很有用。
🌐 This can be useful when there’s a CSS feature you’d like to use in your project that Tailwind doesn’t include utilities for out of the box.
你通过 @layer 添加到 Tailwind 的任何自定义样式都会自动支持 Tailwind 的修饰符语法,用于处理悬停状态、响应式断点、暗黑模式等功能。
🌐 Any custom styles you add to Tailwind with @layer will automatically support Tailwind’s modifier syntax for handling things like hover states, responsive breakpoints, dark mode, and more.
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
.content-auto {
content-visibility: auto;
}
}<div class="lg:dark:content-auto">
<!-- ... -->
</div>在悬停、聚焦及其他状态文档中了解这些修饰符的工作原理。
🌐 Learn more about how these modifiers work in the Hover, Focus, and Other States documentation.
你添加到 base、components 或 utilities 图层的任何自定义样式,只有在你的 HTML 中实际使用这些样式时,才会包含在编译后的 CSS 中。
🌐 Any custom styles you add to the base, components, or utilities layers will only be included in your compiled CSS if those styles are actually used in your HTML.
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
/* This won't be included in your compiled CSS unless you actually use it */
.card {
/* ... */
}
}如果你想添加一些应始终包含的自定义 CSS,请将其添加到你的样式表中,而不要使用 @layer 指令:
🌐 If you want to add some custom CSS that should always be included, add it to your stylesheet without using the @layer directive:
@tailwind base;
@tailwind components;
/* This will always be included in your compiled CSS */
.card {
/* ... */
}
@tailwind utilities;确保将自定义样式放在需要的位置,以获得所需的优先级行为。在上面的示例中,我们在 @tailwind utilities 之前添加了 .card 类,以确保工具类仍然可以覆盖它。
🌐 Make sure to put your custom styles where they need to go to get the precedence behavior you want. In the example above, we’ve added the .card class before @tailwind utilities to make sure utilities can still override it.
如果你编写了大量的 CSS 并将其组织到多个文件中,请确保在使用 Tailwind 处理它们之前将这些文件合并为一个样式表,否则你会看到关于在没有相应 @tailwind 指令的情况下使用 @layer 的错误。
🌐 If you are writing a lot of CSS and organizing it into multiple files, make sure those files are combined into a single stylesheet before processing them with Tailwind, or you’ll see errors about using @layer without the corresponding @tailwind directive.
实现这一点最简单的方法是使用 postcss-import 插件:
🌐 The easiest way to do this is using the postcss-import plugin:
module.exports = {
plugins: {
'postcss-import': {},
tailwindcss: {},
autoprefixer: {},
}
}
在我们的构建时导入文档中了解更多。
🌐 Learn more in our build-time imports documentation.
像 Vue 和 Svelte 这样的组件框架支持在每个组件文件中通过 <style> 块添加每个组件的样式。
🌐 Component frameworks like Vue and Svelte support adding per-component styles within a <style> block that lives in each component file.
虽然你可以在组件样式中使用像 @apply 和 theme 这样的特性,但 @layer 指令将无法工作,并且你会看到关于使用 @layer 而没有对应 @tailwind 指令的错误:
🌐 While you can use features like @apply and theme inside component styles like this, the @layer directive will not work and you’ll see an error about @layer being used without a matching @tailwind directive:
不要在组件样式中使用 @layer
<div>
<slot></slot>
</div>
<style>
/* Won't work because this file is processed in isolation */
@layer components {
div {
background-color: theme('colors.white');
border-radius: theme('borderRadius.lg');
padding: theme('spacing.6');
box-shadow: theme('boxShadow.xl');
}
}
</style>这是因为在底层,像 Vue 和 Svelte 这样的框架会独立处理每一个 <style> 块,并对每一个块单独运行你的 PostCSS 插件链。
🌐 This is because under-the-hood, frameworks like Vue and Svelte are processing every single <style> block independently, and running your PostCSS plugin chain against each one in isolation.
这意味着如果你有 10 个组件,每个组件都有一个 <style> 块,那么 Tailwind 会被运行 10 次,每次运行之间互不知情。因此,Tailwind 无法将你在 @layer 中定义的样式移动到相应的 @tailwind 指令中,因为在 Tailwind 看来,并不存在可以移动的 @tailwind 指令。
🌐 That means if you have 10 components that each have a <style> block, Tailwind is being run 10 separate times, and each run has zero knowledge about the other runs. Because of this, Tailwind can’t take the styles you define in a @layer and move them to the corresponding @tailwind directive, because as far as Tailwind can tell there is no @tailwind directive to move it to.
解决这个问题的一种方法是干脆在组件样式中不要使用 @layer:
🌐 One solution to this is to simply not use @layer inside your component styles:
在不使用 @layer 的情况下添加你的样式
<div>
<slot></slot>
</div>
<style>
div {
background-color: theme('colors.white');
border-radius: theme('borderRadius.lg');
padding: theme('spacing.6');
box-shadow: theme('boxShadow.xl');
}
</style>你会失去控制样式优先级的能力,但不幸的是,由于这些工具的工作方式,这完全不在我们控制范围内。
🌐 You lose the ability to control the precedence of your styles, but unfortunately that’s totally out of our control because of how these tools work.
我们的建议是你根本不要使用这样的组件样式,而是按照 Tailwind 的原意来使用 —— 作为一个全局样式表,直接在你的 HTML 中使用这些类:
🌐 Our recommendation is that you just don’t use component styles like this at all and instead use Tailwind the way it’s intended to be used — as a single global stylesheet where you use the classes directly in your HTML:
使用 Tailwind 的工具类而不是组件样式
<div class="bg-white rounded-lg p-6 shadow-xl">
<slot></slot>
</div>你也可以使用 Tailwind 的插件系统为你的项目添加自定义样式,而不是使用 CSS 文件:
🌐 You can also add custom styles to your project using Tailwind’s plugin system instead of using a CSS file:
const plugin = require('tailwindcss/plugin')
module.exports = {
// ...
plugins: [
plugin(function ({ addBase, addComponents, addUtilities, theme }) {
addBase({
'h1': {
fontSize: theme('fontSize.2xl'),
},
'h2': {
fontSize: theme('fontSize.xl'),
},
})
addComponents({
'.card': {
backgroundColor: theme('colors.white'),
borderRadius: theme('borderRadius.lg'),
padding: theme('spacing.6'),
boxShadow: theme('boxShadow.xl'),
}
})
addUtilities({
'.content-auto': {
contentVisibility: 'auto',
}
})
})
]
}在 插件 文档中了解更多关于编写你自己的插件的信息。
🌐 Learn more about writing your own plugins in the Plugins documentation.