Core concepts
在 Tailwind 项目中添加自定义样式的最佳实践。
在使用框架时,最大的挑战往往是当框架无法满足你的某些需求时,该如何处理。
Tailwind 从一开始就被设计为可扩展和可定制的,因此无论你在构建什么,你都不会感觉在与框架对抗。
本指南涵盖了诸如自定义设计令牌、如何在必要时突破这些约束、添加自定义 CSS 以及通过插件扩展框架等主题。
如果你想更改颜色调色板、间距比例、排版比例或断点等内容,请使用 CSS 中的 @theme 指令添加你的自定义设置:
@theme { --font-display: "Satoshi", "sans-serif"; --breakpoint-3xl: 1920px; --color-avocado-100: oklch(0.99 0 0); --color-avocado-200: oklch(0.98 0.04 113.22); --color-avocado-300: oklch(0.94 0.11 115.03); --color-avocado-400: oklch(0.92 0.19 114.08); --color-avocado-500: oklch(0.84 0.18 117.33); --color-avocado-600: oklch(0.53 0.12 118.34); --ease-fluid: cubic-bezier(0.3, 0, 0, 1); --ease-snappy: cubic-bezier(0.2, 0, 0, 1); /* ... */}了解更多关于自定义主题的信息,请参阅主题变量文档。
虽然你通常可以使用一组受限的设计令牌来构建一个精心设计的项目,但有时你需要突破这些限制以达到像素级的精确。
当你发现自己确实需要像 top: 117px 这样的东西来将背景图像放在正确的位置时,使用 Tailwind 的方括号表示法来生成一个带有任意值的类:
<div class="top-[117px]"> <!-- ... --></div>这基本上就像内联样式,主要的好处是你可以将其与交互修饰符(如 hover)和响应修饰符(如 lg)结合使用:
<div class="top-[117px] lg:top-[344px]"> <!-- ... --></div>这适用于框架中的所有内容,包括背景颜色、字体大小、伪元素内容等:
<div class="bg-[#bada55] text-[22px] before:content-['Festivus']"> <!-- ... --></div>如果你引用的是一个 CSS 变量作为任意值,可以使用自定义属性语法:
<div class="fill-(--my-brand-color) ..."> <!-- ... --></div>这只是 fill-[var(--my-brand-color)] 的简写,它会自动为你添加 var() 函数。
如果你需要使用 Tailwind 没有包含的 CSS 属性,也可以使用方括号表示法来编写完全任意的 CSS:
<div class="[mask-type:luminance]"> <!-- ... --></div>这 真的 就像内联样式,但同样有使用修饰符的好处:
<div class="[mask-type:luminance] hover:[mask-type:alpha]"> <!-- ... --></div>这对于 CSS 变量也很有用,尤其是当它们需要在不同条件下变化时:
<div class="[--scroll-offset:56px] lg:[--scroll-offset:44px]"> <!-- ... --></div>任意 变体 就像任意值,但用于即时选择器修改,就像你可以使用内置的伪类变体(如 hover:{utility})或响应变体(如 md:{utility})一样,但直接在 HTML 中使用方括号表示法。
<ul role="list"> {#each items as item} <li class="lg:[&:nth-child(-n+3)]:hover:underline">{item}</li> {/each}</ul>了解更多信息,请参阅任意变体文档。
当任意值需要包含空格时,使用下划线 (_) 代替,Tailwind 会在构建时自动将其转换为空格:
<div class="grid grid-cols-[1fr_500px_2fr]"> <!-- ... --></div>在下划线常见但空格无效的情况下,Tailwind 会保留下划线而不是将其转换为空格,例如在 URL 中:
<div class="bg-[url('/what_a_rush.png')]"> <!-- ... --></div>在极少数情况下,如果你确实需要使用下划线,但由于空格也是有效的,因此存在歧义,请使用反斜杠转义下划线,Tailwind 不会将其转换为空格:
<div class="before:content-['hello\_world']"> <!-- ... --></div>如果你使用的是 JSX 之类的东西,其中反斜杠会从渲染的 HTML 中删除,请使用 String.raw() 以便反斜杠不会被视为 JavaScript 转义字符:
<div className={String.raw`before:content-['hello\_world']`}> <!-- ... --></div>Tailwind 中的许多实用程序共享一个公共命名空间,但映射到不同的 CSS 属性。例如,text-lg 和 text-black 都共享 text- 命名空间,但一个用于 font-size,另一个用于 color。
在使用任意值时,Tailwind 通常可以根据你传入的值自动处理这种歧义:
<!-- 将生成一个字体大小实用程序 --><div class="text-[22px]">...</div><!-- 将生成一个颜色实用程序 --><div class="text-[#bada55]">...</div>有时确实存在歧义,例如在使用 CSS 变量时:
<div class="text-(--my-var)">...</div>在这些情况下,你可以通过在值之前添加 CSS 数据类型 来“提示” Tailwind 底层类型:
<!-- 将生成一个字体大小实用程序 --><div class="text-(length:--my-var)">...</div><!-- 将生成一个颜色实用程序 --><div class="text-(color:--my-var)">...</div>虽然 Tailwind 旨在处理大部分样式需求,但当你需要时,可以直接编写普通的 CSS:
@import "tailwindcss";.my-custom-style { /* ... */}如果你只想为页面设置一些默认值(如文本颜色、背景颜色或字体系列),最简单的选择是将一些类添加到 html 或 body 元素:
<!doctype html><html lang="en" class="bg-gray-100 font-serif text-gray-900"> <!-- ... --></html>这会将你的基础样式决策与所有其他样式一起保存在标记中,而不是隐藏在单独的文件中。
如果你想为特定的 HTML 元素添加自己的默认基础样式,请使用 @layer 指令将这些样式添加到 Tailwind 的 base 层:
@layer base { h1 { font-size: var(--text-2xl); } h2 { font-size: var(--text-xl); }}使用 components 层添加任何更复杂的类,这些类你希望能够使用实用程序类覆盖。
传统上,这些类通常是 card、btn、badge 之类的类。
@layer components { .card { background-color: var(--color-white); border-radius: var(--rounded-lg); padding: var(--spacing-6); box-shadow: var(--shadow-xl); }}通过在 components 层中定义组件类,你仍然可以在必要时使用实用程序类覆盖它们:
<!-- 看起来像卡片,但有方角 --><div class="card rounded-none"> <!-- ... --></div>使用 Tailwind,你可能不需要像你想象的那样经常使用这些类型的类。阅读我们的管理重复指南,了解我们的建议。
components 层也是放置任何第三方组件的自定义样式的好地方:
@layer components { .select2-dropdown { /* ... */ }}除了使用 Tailwind 附带的实用程序外,你还可以添加自己的自定义实用程序。当你想在项目中使用 Tailwind 没有包含的 CSS 功能时,这会很有用。
使用 @utility 指令将自定义实用程序添加到项目中:
@utility content-auto { content-visibility: auto;}你现在可以在 HTML 中使用这个实用程序:
<div class="content-auto"> <!-- ... --></div>它也可以与 hover、focus 和 lg 等变体一起使用:
<div class="hover:content-auto"> <!-- ... --></div>自定义实用程序会自动插入到 utilities 层,与框架中的所有内置实用程序一起。
如果你的自定义实用程序比单个类名更复杂,请使用嵌套来定义实用程序:
@utility scrollbar-hidden { &::-webkit-scrollbar { display: none; }}除了使用 @utility 指令注册简单实用程序外,你还可以注册接受参数的功能性实用程序:
@utility tab-* { tab-size: --value(--tab-size-*);}特殊的 --value() 函数用于解析实用程序值。
使用 --value(--theme-key-*) 语法将实用程序值解析为一组主题键:
@theme { --tab-size-2: 2; --tab-size-4: 4; --tab-size-github: 8;}@utility tab-* { tab-size: --value(--tab-size-*);}这将匹配 tab-1、tab-4 和 tab-github 等实用程序。
要将值解析为裸值,请使用 --value({type}) 语法,其中 {type} 是你想要验证裸值的数据类型:
@utility tab-* { tab-size: --value(integer);}这将匹配 tab-1 和 tab-76 等实用程序。
要支持任意值,请使用 --value([{type}]) 语法(注意方括号),以告诉 Tailwind 支持哪些类型作为任意值:
@utility tab-* { tab-size: --value([integer]);}这将匹配 tab-[1] 和 tab-[76] 等实用程序。如果你想支持任何数据类型,可以使用 --value([*])。
--value() 函数的所有三种形式都可以在规则中用作多个声明,任何未能解析的声明将在输出中省略:
@theme { --tab-size-github: 8;}@utility tab-* { tab-size: --value([integer]); tab-size: --value(integer); tab-size: --value(--tab-size-*);}这使得在每种情况下都可以根据需要以不同方式处理返回值,例如将裸整数转换为百分比:
@utility opacity-* { opacity: --value([percentage]); opacity: calc(--value(integer) * 1%); opacity: --value(--opacity-*);}--value() 函数还可以接受多个参数,并从左到右解析它们,如果你不需要在不同情况下以不同方式处理返回值:
@theme { --tab-size-github: 8;}@utility tab-* { tab-size: --value(--tab-size-*, integer, [integer]);}@utility opacity-* { opacity: calc(--value(integer) * 1%); opacity: --value(--opacity-*, [percentage]);}要支持负值,请将正负实用程序分别注册为单独的声明:
@utility inset-* { inset: calc(--var(--spacing) * --value([percentage], [length]));}@utility -inset-* { inset: calc(--var(--spacing) * --value([percentage], [length]) * -1);}修饰符使用 --modifier() 函数处理,该函数的工作方式与 --value() 函数完全相同,但在存在修饰符时操作:
@utility text-* { font-size: --value(--font-size-*, [length]); line-height: --modifier(--line-height-*, [length], [*]);}如果没有修饰符,任何依赖修饰符的声明都不会包含在输出中。
要处理分数,我们依赖 CSS ratio 数据类型。如果将其与 --value() 一起使用,这是一个信号,告诉 Tailwind 将值和修饰符视为单个值:
@utility aspect-* { aspect-ratio: --value(--aspect-ratio-*, ratio, [ratio]);}这将匹配 aspect-square、aspect-3/4 和 aspect-[7/9] 等实用程序。
使用 @variant 指令在自定义 CSS 中应用 Tailwind 变体:
.my-element { background: white; @variant dark { background: black; }}如果你需要同时应用多个变体,请使用嵌套:
.my-element { background: white; @variant dark { @variant hover { background: black; } }}