Lzh on GitHub

添加自定义样式

在 Tailwind 项目中添加您自己的自定义样式的最佳实践。

在使用框架时,经常遇到的最大挑战是当框架无法处理您需要的东西时,您应该怎么做。

Tailwind 从一开始就被设计成可扩展和可定制的,因此无论您构建什么,都不会觉得在与框架作斗争。

本指南涵盖了诸如自定义 设计令牌、必要时如何打破这些约束、新增您自己的自定义 CSS 以及使用插件扩展框架等主题。

自定义您的主题

如果您想更改颜色调色板、间距比例、排版比例或断点等内容,请在您的 CSS 中使用 @theme 指令新增您的自定义设置:

CSS
@theme {
  --font-display: "Satoshi", "sans-serif";
  
  --breakpoint-3xl: 120rem;
  
  --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 的 方括号 表示法来即时生成具有任何任意值的类

HTML
<div class="top-[117px]">
  <!-- ... -->
</div>

这基本上就像内联样式,但主要优点是您可以将其与交互修饰符(如 hover)和响应式修饰符(如 lg:)结合使用:

HTML
<div class="top-[117px] lg:top-[344px]">
  <!-- ... -->
</div>

这适用于框架中的所有内容,包括背景颜色、字体大小、伪元素内容等等:

HTML
<div class="bg-[#bada55] text-[22px] before:content-['Festivus']">
  <!-- ... -->
</div>

如果您引用 CSS 变量作为任意值,可以使用自定义属性语法:

HTML
<div class="fill-(--my-brand-color) ...">
  <!-- ... -->
</div>

这只是 fill-[var(--my-brand-color)] 的简写形式,它会自动为您添加 var() 函数。

任意属性

如果您需要使用 Tailwind 默认没有提供的 CSS 属性,您也可以使用方括号表示法来编写完全任意的 CSS:

HTML
<div class="[mask-type:luminance]">
  <!-- ... -->
</div>

真的 就像内联样式,但同样具有可以使用修饰符的优点:

HTML
<div class="[mask-type:luminance] hover:[mask-type:alpha]">
  <!-- ... -->
</div>

这对于 CSS 变量也很有用,尤其是在它们需要在不同条件下更改时:

HTML
<div class="[--scroll-offset:56px] lg:[--scroll-offset:44px]">
  <!-- ... -->
</div>

任意变体

任意 变体 就像任意值,但用于即时修改选择器,就像您可以使用内建的伪类变体(如 hover:{utility})或响应式变体(如 md:{utility})一样,但直接在您的 HTML 中使用方括号表示法。

HTML
<ul role="list">
  {#each items as item}
  <li class="lg:[&:nth-child(-n+3)]:hover:underline">{item}</li>
  {/each}
</ul>

任意变体文档 中了解更多信息。

处理空白

当任意值需要包含空格时,请使用下划线 (_) 代替,Tailwind 会在构建时自动将其转换为空格:

HTML
<div class="grid grid-cols-[1fr_500px_2fr]">
  <!-- ... -->
</div>

在下划线常见但空格无效的情况下,Tailwind 会保留下划线而不是将其转换为空格,例如在 URL 中:

HTML
<div class="bg-[url('/what_a_rush.png')]">
  <!-- ... -->
</div>

在极少数情况下,您确实需要使用下划线但由于空格也有效而导致含糊不清时,请使用反斜线来转义下划线,Tailwind 将不会将其转换为空格:

HTML
<div class="before:content-['hello\_world']">
  <!-- ... -->
</div>

如果您正在使用像 JSX 这样会从渲染的 HTML 中剥离反斜线的工具,请使用 String.raw(),这样反斜线就不会被视为 JavaScript 的转义字符:

HTML
<div className={String.raw`before:content-['hello\_world']`}>
  <!-- ... -->
</div>

解决歧义

Tailwind 中的许多工具类共享一个通用命名空间,但映射到不同的 CSS 属性。例如,text-lgtext-black 都共享 text- 命名空间,但一个用于 font-size,另一个用于 color

当使用任意值时,Tailwind 通常可以根据您传入的值自动处理这种歧义:

HTML
<!-- Will generate a font-size utility -->
<div class="text-[22px]">...</div>

<!-- Will generate a color utility -->
<div class="text-[#bada55]">...</div>

但有时确实会出现歧义,例如在使用 CSS 变量时:

HTML
<div class="text-(--my-var)">...</div>

在这些情况下,您可以通过在值之前添加 CSS 数据类型 来 “提示” Tailwind 底层的类型:

HTML
<!-- Will generate a font-size utility -->
<div class="text-(length:--my-var)">...</div>

<!-- Will generate a color utility -->
<div class="text-(color:--my-var)">...</div>

使用自定义 CSS

虽然 Tailwind 旨在处理您的大部分样式需求,但当您需要时,完全可以编写纯 CSS:

CSS
@import "../../../../../node_modules/.pnpm/tailwindcss@4.1.11/node_modules/tailwindcss/dist/lib.d.mts";

.my-custom-style {
    /* ... */
}

添加基础(base)样式

如果您只想为 页面设置 一些默认样式(例如文本颜色、背景颜色或字体),最简单的方法是直接在 htmlbody 元素上添加一些类:

HTML
<!doctype html>
<html lang="en" class="bg-gray-100 font-serif text-gray-900">
    <!-- ... -->
</html>

这样可以将您的基础样式决策保留在您的标记中,与所有其他样式放在一起,而不是将它们隐藏在单独的文件中。

如果您想为 特定的 HTML 元素 添加自己的默认基础样式,请使用 @layer 指令将这些样式添加到 Tailwind 的 base 层:

CSS
@layer base {
  h1 {
    font-size: var(--text-2xl);
  }
  h2 {
    font-size: var(--text-xl);
  }
}

添加组件类(components)

对于希望在项目中添加的更复杂的类,同时仍希望通过工具类进行覆盖的情况,请使用 components 层。

传统上,这些将是像 cardbtnbadge 这样的类。

CSS
@layer components {
  .card {
    background-color: var(--color-white);
    border-radius: var(--rounded-lg);
    padding: var(--spacing-6);
    box-shadow: var(--shadow-xl);
  }
}

通过在 components 层中定义组件类,您仍然可以在必要时使用工具类来覆盖它们:

HTML
<!-- Will look like a card, but with square corners -->
<div class="card rounded-none">
  <!-- ... -->
</div>

使用 Tailwind,您可能不需要像您想象的那么多这种类型的类。请阅读我们的 管理重复 指南以了解我们的建议。

components 层也是放置您正在使用的任何第三方组件的自定义样式的好地方:

CSS
@layer components {
  .select2-dropdown {
    /* ... */
  }
}

使用变体

使用 @variant 指令在自定义 CSS 中应用 Tailwind 变体:

app.css
.my-element {
  background: white;
  
  @variant dark {
    background: black;
  }
}
Compiled CSS
.my-element {
  background: white;
  
  @media (prefers-color-scheme: dark) {
    background: black;
  }
}

如果您需要同时应用多个变体,请使用嵌套结构:

app.css
.my-element {
  background: white;
  
  @variant dark {
    @variant hover {
      background: black;
    }
  }
}
Compiled CSS
.my-element {
  background: white;
  
  @media (prefers-color-scheme: dark) {
    &:hover {
      @media (hover: hover) {
        background: black;
      }
    }
  }
}

添加自定义工具类(utilities)

简单工具类

除了使用 Tailwind 附带的工具类之外,您还可以添加自己的自定义工具类。当您想在项目中使用 Tailwind 默认没有提供的 CSS 功能时,这非常有用。

使用 @utility 指令将自定义工具类添加到您的项目中:

CSS
@utility content-auto {
  content-visibility: auto;
}

您现在可以在您的 HTML 中使用这个工具类:

HTML
<div class="content-auto">
  <!-- ... -->
</div>

它也适用于 hoverfocuslg: 等变体:

HTML
<div class="hover:content-auto">
  <!-- ... -->
</div>

自定义工具类会与框架中所有内建的工具类一起自动插入到 utilities 层中。

复杂工具类

如果您的自定义工具类比单个类名更复杂,请使用嵌套结构来定义该工具类:

CSS
@utility scrollbar-hidden {
  &::-webkit-scrollbar {
    display: none;
  }
}

函数工具类

除了使用 @utility 指令注册简单的工具类之外,您还可以注册 接受参数 的函数工具类:

CSS
@utility tab-* {
  tab-size: --value(--tab-size-*);
}

特殊的 --value() 函数用于解析工具类的值。

匹配主题值

使用 --value(--theme-key-*) 语法将工具类的值解析为一组主题键:

CSS
@theme {
  --tab-size-2: 2;
  --tab-size-4: 4;
  --tab-size-github: 8;
}

@utility tab-* {
  tab-size: --value(--tab-size-*);
}

这将匹配像 tab-2tab-4tab-github 这样的工具类。

裸值

要将值解析为裸值,请使用 --value({type}) 语法,其中 {type} 是您想要验证裸值的 CSS 数据类型

@utility tab-* {
  tab-size: --value(integer);
}

这将匹配像 tab-1tab-76 这样的工具类。

字面值

要支持字面值,请使用 --value('literal') 语法(注意引号):

@utility tab-* {
  tab-size: --value('inherit', 'initial', 'unset');
}

这将匹配像 tab-inherittab-initialtab-unset 这样的工具类。

任意值

要支持任意值,请使用 --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-*);
}

这使得在必要时可以针对每种情况以不同的方式处理值,例如将裸整数转换为百分比:

CSS
@utility opacity-* {
  opacity: --value([percentage]);
  opacity: calc(--value(integer) * 1%);
  opacity: --value(--opacity-*);
}

--value() 函数也可以接受多个参数,如果您不需要在不同情况下以不同的方式处理返回值,则会从左到右解析它们:

CSS
@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]);
}

负值

要支持负值,请将正值和负值工具类注册到不同的声明中:

CSS
@utility inset-* {
  inset: calc(var(--spacing) * --value([percentage], [length]));
}

@utility -inset-* {
  inset: calc(var(--spacing) * --value([percentage], [length]) * -1);
}

修饰符

修饰符是使用 --modifier() 函数处理的,该函数的工作方式与 --value() 函数完全相同,但操作的是修饰符(如果存在):

CSS
@utility text-* {
  font-size: --value(--text-*, [length]);
  line-height: --modifier(--leading-*, [length], [*]);
}

如果没有修饰符,则任何依赖修饰符的声明都不会包含在输出中。

分数

为了处理分数,我们依赖 CSS 的 ratio 数据类型。如果将其与 --value() 一起使用,则表示 Tailwind 将值和修饰符视为单个值:

CSS
@utility aspect-* {
  aspect-ratio: --value(--aspect-ratio-*, ratio, [ratio]);
}

这将匹配像 aspect-squareaspect-3/4aspect-[7/9] 这样的工具类。

添加自定义变体

除了使用 Tailwind 附带的变体之外,您还可以使用 @custom-variant 指令添加自己的自定义变体:

CSS
@custom-variant theme-midnight {
  &:where([data-theme="midnight"] *) {
    @slot;
  }
}

现在您可以在您的 HTML 中使用 theme-midnight:<utility> 变体:

HTML
<html data-theme="midnight">
  <button class="theme-midnight:bg-black ..."></button>
</html>

当不需要嵌套时,您可以使用简写语法创建变体:

CSS
@custom-variant theme-midnight (&:where([data-theme="midnight"] *));

当自定义变体有多个规则时,它们可以相互嵌套:

CSS
@custom-variant any-hover {
  @media (any-hover: hover) {
    &:hover {
      @slot;
    }
  }
}