Tailwind

Tailwind CSS 中文文档

Tailwind CSS 中文文档

https://www.tailwindcss.cn

他的组件库叫:shadcn/ui

image-20250919212644332

1. Tailwind CSS 是基础

  • Tailwind CSS 是一个实用类优先的 CSS 框架。
  • 它本身不提供组件,而是提供一套原子化的 CSS 工具类(如 flex, p-4, text-gray-700),让开发者自己快速组合 UI。
  • 优点是灵活、可定制,但缺点是需要自己写组件,容易出现重复劳动。

2. shadcn/ui 是组件集合

  • shadcn/ui 本质上是基于 Radix UI + Tailwind CSS 的一个组件库。
  • 它并不是一个单独发布的 npm 包,而是提供一组 可以拷贝进自己项目的组件源码
  • 每个组件都用 Tailwind CSS 来写样式,用 Radix UI 提供的可访问性(accessibility)和交互逻辑。
  • 举个例子:
    • Tailwind 给出“积木” → flex items-center rounded-md px-4
    • Radix 提供“行为” → Dialog、Dropdown、Popover 等
    • shadcn/ui 把它们拼好 → Button、Dialog、DropdownMenu 等可直接用的组件。

Radix UI 是什么?

  • Radix UI 是一个 无样式(unstyled) 的 React 组件库。
  • 它专注于实现 无障碍(Accessibility, a11y)交互逻辑,但不负责外观样式。
  • 这些组件是 “头脑”,而不是“外表”:
    • 例如一个 <Dialog />,Radix 负责 打开/关闭、焦点管理、键盘导航、ARIA 属性
    • 但样式(颜色、边框、阴影等)你得自己写。

备注

只能在react里面使用

基础介绍

现在就不讲前面的组件UI了,我们来直接讲Tailwind CSS吧,以后自己写组件库得了

只需书写 HTML 代码,无需书写 CSS,即可快速构建美观的网站。

Tailwind CSS 的工作原理是扫描所有 HTML 文件、JavaScript 组件以及任何 模板中的 CSS 类(class)名,然后生成相应的样式代码并写入 到一个静态 CSS 文件中。

他快速、灵活、可靠,没有运行时负担。

安装

它提供了多种安装使用方式,这里使用vite这种吧,可以融入vue3

创建项目

如果您尚未设置好 Vite 项目,请先创建一个新的 Vite 项目。最常见的方法是使用 [创建 Vite]

shell
npm create vite@latest my-project -- --template vuecd my-project
#在下面你就可以选择项目,比如选择vue项目,这是创建vue项目一种方式
#你也可以选择创建vue项目,使用vue官方创建命令
npm create vue@lasted

安装 Tailwind CSS与使用

3.x版本

npm安装

安装 tailwindcss 及其依赖项,然后生成您的 tailwind.config.jspostcss.config.js 文件。

shell
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
#npx 是 Node.js 自带的一个工具(从 npm 5.2.0 开始就有了),它的作用是 直接运行 npm 包里的可执行命令,而不用你手动去全局安装。
配置您的模板路径

在您的 tailwind.config.js 文件中添加所有模板文件的路径。

js
/** @type {import('tailwindcss').Config} */
export default {
content: [
 "./index.html",
 "./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
 extend: {},
},
plugins: [],
}

告诉 Tailwind 去扫描哪些文件,提取里面用到的类名。

  • "./index.html" → 项目的入口 HTML
  • "./src/**/*.{vue,js,ts,jsx,tsx}" → src 目录下所有 Vue / TS / JS 文件

Tailwind 会根据你在这些文件里写的类(比如 bg-red-500flex),只生成对应的 CSS,保证打包后的文件很小。

如果不配这个,Tailwind 可能生成一大堆没用的样式,导致体积非常大。

将 Tailwind 指令添加到您的 CSS 中

在您的 ./src/style.css 文件中添加 Tailwind 的每一层的 @tailwind 指令。 style.css

css
@tailwind base;
@tailwind components;
@tailwind utilities;

告诉 Tailwind 要生成哪些层级的样式:

  • @tailwind base; → 一些浏览器默认样式的 reset(相当于 normalize.css)
  • @tailwind components; → Tailwind 的组件样式(比如 prosecontainer 等)
  • @tailwind utilities; → 大量的工具类(flexp-4text-lg 等)

⚡ 注意:这里必须写在 .css 文件里(比如 src/style.css),不能写在 TS 文件里。

最后你需要在入口文件 main.ts 里引入它:

ts
import './style.css'

4.x版本

npm安装
shell
npm install tailwindcss @tailwindcss/vite
配置 Vite 插件

@tailwindcss/vite 插件添加到您的 Vite 配置中。

vite.config.ts

ts
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'

export default defineConfig({
  plugins: [
    tailwindcss(),
  ],
})
导入 Tailwind CSS

在您的 CSS 文件中添加 @import,以导入 Tailwind CSS。

css
@import "tailwindcss";
启动您的构建流程

使用 npm run dev 或在您的 package.json 文件中配置的任何命令运行您的构建流程。

bash
npm run dev
开始在您的 HTML 中使用 Tailwind

确保您的编译后的 CSS 已包含在 <head> 中*(您的框架可能会为您处理此问题)*,然后开始使用 Tailwind 的实用程序类来设置您的内容样式。

html
<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="/src/styles.css" rel="stylesheet">
</head>
<body>
  <h1 class="text-3xl font-bold underline">
    Hello world!
  </h1>
</body>
</html>

基础样式重置

当您导入tailwindcss到项目时,Preflight 会自动注入到base图层中:

css
@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/preflight.css" layer(base);
@import "tailwindcss/utilities.css" layer(utilities);

Tailwind CSS v4(即未来版本或当前的 Canary / Alpha 版本) 中,如果你不想要它的 preflight(基础样式重置),可以通过配置文件关闭。


✅ 方法一:在 tailwind.config.js 中禁用 preflight
js
// tailwind.config.js
export default {
  corePlugins: {
    preflight: false,
  },
}

这行配置会彻底禁用 Tailwind 的基础样式重置(即 @tailwind base 不会注入 Normalize/Preflight 规则)。


✅ 方法二:在 CSS 中不引入 @tailwind base

如果你只是想手动控制样式层,可以这样:

css
@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/utilities.css" layer(utilities);

区别

配置文件

Tailwind v4,这个版本和 v3 最大的不同就是:

tailwind.config.js 不再是必需的

为什么不需要 config 文件?

  • v3:Tailwind 需要 config 文件来告诉它 去哪些文件里扫描 class 名,否则打包出来会特别大。
  • v4:Tailwind 引入了 Content-aware CSS engine,它会自动扫描你的整个项目(HTML / Vue / TSX / JSX 等),不需要你手动列路径。

所以,如果你只是用默认配置,不需要写 tailwind.config.js

什么时候需要 tailwind.config.js

只有当你要做自定义时才需要:

  • 新增主题颜色 / 字体 / spacing 等
  • 使用插件
  • 配置 safelist(强制保留某些类)

比如:

js
// tailwind.config.js
export default {
  theme: {
    extend: {
      colors: {
        brand: "#1DA1F2",
      },
    },
  },
}
导入样式

Tailwind v4 (2024 年出的最新版本) 官方改成了 零配置模式 (zero-config),所以可以直接写:

直接在 index.css 或者 src/assets/main.css(取决于你项目结构)里写:

@import "tailwindcss";

这一条 import 就等价于旧版的三条 @tailwind 指令。它会自动把 base/components/utilities 都引进来。

/* src/index.css */
@import "tailwindcss";
// src/main.ts
import './index.css'

为什么不直接在main.ts使用import "tailwindcss"

1. tailwindcss 是个 PostCSS 插件

  • 它不是纯 CSS 文件,而是一个 框架工具,需要在构建阶段编译成最终的 CSS。
  • 直接 import 'tailwindcss',Vite 不会把它当作样式处理,而是尝试去加载一个 Node 包 → 会报错。

2. 正确姿势是 @import "tailwindcss";

  • 这个写在 .css 文件里时,Vite + PostCSS 才能识别它,让 Tailwind 在编译时生成对应的样式。
  • 换句话说:Tailwind 的入口必须在 CSS 层,而不是 TS 层。

3. 为什么要单独建 index.css

  • Tailwind 在构建时需要一个明确的 CSS 文件入口,扫描其中的 @import "tailwindcss"; 来生成样式。
  • 你把它放在 main.ts → JS 执行阶段才会加载,不符合 Tailwind 的工作流程。

编辑器设置

使用 Tailwind CSS 时改善开发人员体验的工具。

语法支持

Tailwind CSS 使用自定义 CSS 语法,如@theme@variant@source,在某些编辑器中,如果这些规则无法识别,则可能会触发警告或错误。

如果您使用的是 VS Code,我们的官方Tailwind CSS IntelliSense插件包含专用的 Tailwind CSS 语言模式,该模式支持 Tailwind 使用的所有自定义规则和函数。

在某些情况下,如果您的编辑器对 CSS 文件中的语法要求非常严格,则可能需要禁用本机 CSS linting/验证。

VS Code 的 IntelliSense

Visual Studio Code 的官方Tailwind CSS IntelliSense扩展通过为用户提供自动完成、语法突出显示和 linting 等高级功能增强了 Tailwind 开发体验。

  • 自动完成——为实用程序类以及CSS 函数和指令提供智能建议。
  • Linting — 突出显示 CSS 和标记中的错误和潜在缺陷。
  • 悬停预览- 当您将鼠标悬停在实用程序类上时,会显示其完整的 CSS。
  • 语法高亮——以便正确高亮使用自定义 CSS 语法的 Tailwind 功能。

查看GitHub 上的项目以了解更多信息,或将其添加到 Visual Studio Code以立即开始。

使用 Prettier 进行类别排序

我们为 Tailwind CSS 维护一个官方的Prettier 插件,它会按照我们推荐的类顺序自动对您的类进行排序。

img

它可以与自定义 Tailwind 配置无缝协作,并且由于它只是一个 Prettier 插件,因此它可以在 Prettier 工作的任何地方工作 - 包括每个流行的编辑器和 IDE,当然还有命令行。

html
<!-- Before -->
<button class="text-white px-4 sm:px-8 py-2 sm:py-3 bg-sky-700 hover:bg-sky-800">Submit</button>
<!-- After -->
<button class="bg-sky-700 px-4 py-2 text-white hover:bg-sky-800 sm:px-8 sm:py-3">Submit</button>

查看GitHub 上的插件以了解更多信息并开始使用。

JetBrains IDE

JetBrains IDE(例如 WebStorm、PhpStorm 等)支持 HTML 中的智能 Tailwind CSS 补全。

详细了解 JetBrains IDE 中的 Tailwind CSS 支持 →

泽德

Zed 内置支持多种语言的 Tailwind CSS 自动完成、linting 和悬停预览。它还支持 Prettier,因此我们的官方Prettier 插件在安装后即可在 Zed 中无缝运行。

Tailwind核心概念

Utility-First的基本原理

遵循工具类优先的流程(utility-first workflow)并基于一套具有约束性的基本工具类来构建 复杂的组件。

传统上,每当您需要在web上设置某些样式时,您都会编写 CSS。

使用传统方法,自定义设计需要自定义 CSS。使用 Tailwind,您可以通过直接在 HTML 中应用预先存在的类来设置元素的样式。使用实用程序类构建自定义设计而无需编写 CSS

css
<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center gap-x-4">
  <div class="shrink-0">
    <img class="size-12" src="/img/logo.svg" alt="ChitChat Logo">
  </div>
  <div>
    <div class="text-xl font-medium text-black">ChitChat</div>
    <p class="text-slate-500">You have a new message!</p>
  </div>
</div>

在上面的例子中,我们使用了:

  • Tailwind 的flexboxpadding的使用(flexshrink-0p-6)用于控制整体卡片布局
  • max-widthmargin的使用(max-w-smmx-auto)用于限制卡片宽度并将其水平居中
  • background-colorborder-radiusbox-shadow的使用(bg-whiterounded-xlshadow-lg)用于设置卡片的外观
  • The size 工具(size-12) 设置logo的宽高
  • The gap 工具(gap-x-4) 解决logo和文本的间隔

这种方法使我们能够实现完全自定义的组件设计,而无需编写一行自定义 CSS。

现在我知道你在想什么了:*“这简直是暴行,简直是一团糟!”*你说得对,它确实有点丑。事实上,你第一次看到它时几乎不可能觉得这是个好主意——你必须亲自尝试一下

但是一旦你真正以这种方式构建了某些东西,你很快就会注意到一些非常重要的好处:

  • 你不用再浪费精力去发明类名了。不用再为了给某个东西添加样式而添加一些愚蠢的类名sidebar-inner-wrapper,也不用再为一个其实只是 flex 容器的东西苦苦思索一个完美的抽象名称了。
  • 你的 CSS 代码不再增长。使用传统方法,每次添加新功能,你的 CSS 文件都会变得越来越大。使用实用程序,所有内容都可以复用,因此你几乎不需要编写新的 CSS 文件。
  • 修改更安全。CSS 是全局的,你永远不知道修改后会破坏什么。HTML 中的类是本地的,所以你可以修改它们,而不必担心会破坏其他部分。

当您意识到使用预定义的实用程序类在 HTML 中工作可以多么高效时,以任何其他方式工作都会感觉像是一种折磨。

为什么不直接使用内联样式?

对这种方法的常见反应是想知道“这不就是内联样式吗?”并且在某些方面它是 - 您将样式直接应用于元素,而不是为它们分配类名,然后设置该类的样式。

但是使用实用程序类比内联样式有几个重要的优点:

  • 使用约束进行设计。使用内联样式,每个值都是一个神奇的数字。使用实用程序,您可以从预定义的设计系统中选择样式,这使得构建视觉一致的UI变得更加容易。
  • 响应式设计。您无法在内联样式中使用媒体查询,但可以使用 Tailwind 的响应式实用程序轻松构建完全响应的界面。
  • 悬停、聚焦和其他状态。内联样式无法针对悬停或聚焦等状态,但 Tailwind 的状态变体可以轻松地使用实用程序类来设置这些状态的样式。

该组件具有完全响应能力,包含具有悬停和焦点样式的按钮,并且完全由实用程序类构建:

处理 Hover, Focus, and 以及其他状态

使用条件标识符(conditional modifiers)可以为处于交互状态(如鼠标悬停、聚焦等)中的元素设置 样式。

Tailwind 中的每个工具类都可以通过在类名的开头添加修饰符来有条件地启用,该修饰符描述了您想要针对的条件。

例如,要类bg-sky-700hover状态时启用,请使用“hover:bg-sky-700`

html
<button class="bg-sky-500 hover:bg-sky-700 ...">
  Save changes
</button>

Tailwind 包含几乎所有您需要的修饰符,包括:

  • 伪类,例如:hover,,,和:focus``:first-child``:required
  • 伪元素,例如::before,,,和::after``::placeholder``::selection
  • 媒体查询和特征查询,例如响应式断点(@media(min-width))、dark模式和prefers-reduced-motion
  • 属性选择器,例如[dir="rtl"][open]

这些修饰符甚至可以堆叠以针对更具体的情况,例如在黑暗模式下、在响应式断点处、在悬停时更改背景颜色:

html
<button class="dark:md:hover:bg-fuchsia-600 ...">
  Save changes
</button>

注意

Tailwind CSS 里,medium breakpoint 指的是一个 断点(breakpoint),用来在不同屏幕大小下切换样式。

Tailwind 内建了一组 响应式断点(默认配置),分别对应常见屏幕宽度。比如默认配置是这样的(取自 tailwind.config.js):

module.exports = {
  theme: {
    screens: {
      sm: '640px',   // small
      md: '768px',   // medium
      lg: '1024px',  // large
      xl: '1280px',  // extra large
      2xl: '1536px', // 2x extra large
    },
  },
}

所以:

  • md (medium) 就表示 当视口宽度 ≥ 768px 时生效
  • 它是 移动优先 (mobile-first) 的写法,也就是说,不加前缀的样式默认应用在所有屏幕上,而带 md: 的样式只有在 768px 及以上的屏幕 才应用。

在本指南中,您将了解框架中可用的每个修饰符,如何将它们与您自己的自定义类一起使用,甚至如何创建您自己的修饰符。

Hover, focus, and active

使用 hover, focus, active 来修改处于hover, focus, 和 active状态的元素样式:

html
<button class="bg-violet-500 hover:bg-violet-600 active:bg-violet-700 focus:outline-none focus:ring focus:ring-violet-300 ...">
  Save changes
</button>

Tailwind 还包括其他交互状态的修饰符,如、、:visited等等。:focus-within:focus-visible

请参阅伪类参考以获取可用伪类修饰符的完整列表。

First, last, odd, and even

当元素是第一个子元素或最后一个子元素时,使用firstlast修饰符设置其样式:

当元素是奇数或偶数子元素时,您还可以使用oddeven修饰符来设置元素的样式:

html
<table>
  <!-- ... -->
  <tbody>
    {#each people as person}
      <!-- Use a white background for odd rows, and slate-50 for even rows -->
      <tr class="odd:bg-white even:bg-slate-50">
        <td>{person.name}</td>
        <td>{person.title}</td>
        <td>{person.email}</td>
      </tr>
    {/each}
  </tbody>
</table>

Tailwind 还包括其他结构伪类的修饰符:only-child,如:first-of-type、、:empty等。

请参阅伪类参考以获取可用伪类修饰符的完整列表。

表单状态

使用诸如 required, invalid, 和disabled这样的修饰词来对处于不同状态的样式元素进行设置。

html
<input
  type="text"
  value="tbone"
  disabled
  class="invalid:border-pink-500 invalid:text-pink-600 focus:border-sky-500 focus:outline focus:outline-sky-500 focus:invalid:border-pink-500 focus:invalid:outline-pink-500 disabled:border-gray-200 disabled:bg-gray-50 disabled:text-gray-500 disabled:shadow-none dark:disabled:border-gray-700 dark:disabled:bg-gray-800/20 ..."
/>

为此类事物使用变体可以减少模板中的条件逻辑量,使您可以根据输入所处的状态使用同一组类,并让浏览器为您应用正确的样式。

Tailwind 还包括其他表单状态的变体,例如 :read-only:indeterminate:checked 等。

:has()

使用 has-* 变体根据元素后代的状态或内容设置元素的样式

html
<label
  class="has-checked:bg-indigo-50 has-checked:text-indigo-900 has-checked:ring-indigo-200 dark:has-checked:bg-indigo-950 dark:has-checked:text-indigo-200 dark:has-checked:ring-indigo-900 ..."
>
  <svg fill="currentColor">
    <!-- ... -->
  </svg>
  Google Pay
  <input type="radio" class="checked:border-indigo-500 ..." />
</label>

选中状态的改变:

image-20250920164832649

您可以将 has-* 与伪类一起使用,例如 has-[:focus],以根据元素后代的状态设置元素的样式。您还可以使用元素选择器,例如 has-[img]has-[a],以根据元素后代的内容设置元素的样式。

基于组的后代设置样式

如果您需要根据父元素的后代设置元素的样式,则可以将父元素标记为 group 类,并使用 group-has-* 变体来设置目标元素的样式

html
<div class="group ...">
  <img src="..." />
  <h4>Spencer Sharp</h4>
  <svg class="hidden group-has-[a]:block ..."><!-- ... --></svg>
  <p>Product Designer at <a href="...">planeteria.tech</a></p>
</div>

image-20250920164725801

有链接右上角有跳转的图标,没有链接就没有图标

基于同级元素的后代设置样式

如果您需要根据兄弟元素的后代设置元素的样式,则可以将兄弟元素标记为 peer 类,并使用 peer-has-* 变体来设置目标元素的样式

html
<div>
  <label class="peer ...">
    <input type="checkbox" name="todo[1]" checked />
    Create a to do list
  </label>
  <svg class="peer-has-checked:hidden ..."><!-- ... --></svg>
</div>

image-20250920165045801

勾选之后文字删除线处理,后面的删除号消失

:not()

当条件不为真时,使用 not- 变体设置元素的样式。

当与其他伪类变体结合使用时,它特别强大,例如将 not-focus:hover: 结合使用,以仅在元素未聚焦时应用悬停样式

html
<button class="bg-indigo-600 hover:not-focus:bg-indigo-700">
  <!-- ... -->
</button>

您还可以将 not- 变体与媒体查询变体(例如 forced-colorssupports)结合使用,以仅在用户的环境不为真时设置元素的样式

html
<div class="not-supports-[display:grid]:flex">
  <!-- ... -->
</div>

基于父状态设置样式

当您需要根据某些元素的状态设置元素的样式时,请将父元素标记为 group 类,并使用 group-* 变体(例如 group-hover)来设置目标元素的样式

html
<a href="#" class="group ...">
  <div>
    <svg class="stroke-sky-500 group-hover:stroke-white ..." fill="none" viewBox="0 0 24 24">
      <!-- ... -->
    </svg>
    <h3 class="text-gray-900 group-hover:text-white ...">New project</h3>
  </div>
  <p class="text-gray-500 group-hover:text-white ...">Create a new project from a variety of starting templates.</p>
</a>

悬停在卡片上以查看两个文本元素的颜色变化

区分嵌套组

嵌套组时,您可以通过使用 group/{name} 类为该父级指定唯一的组名称,并使用诸如 group-hover/{name} 之类的类将该名称包含在变体中,从而根据特定父组的状态设置某些内容的样式

html
<ul role="list">
  {#each people as person}
    <li class="group/item ...">
      <!-- ... -->
      <a class="group/edit invisible group-hover/item:visible ..." href="tel:{person.phone}">
        <span class="group-hover/edit:text-gray-700 ...">Call</span>
        <svg class="group-hover/edit:translate-x-0.5 group-hover/edit:text-gray-500 ..."><!-- ... --></svg>
      </a>
    </li>
  {/each}
</ul>
<!--链接标签a的名称是edit,整个列表组名称是item-->

组可以随意命名,无需以任何方式配置 — 只需在标记中直接命名您的组,Tailwind 就会自动生成必要的 CSS。

任意组

您可以通过在方括号之间提供您自己的选择器作为任意值来动态创建一次性 group-* 变体

html
<div class="group is-published">
  <div class="hidden group-[.is-published]:block">
    Published
  </div>
</div>

生成的CSS

css
.group-[.is-published]:block {
  &:is(:where(.group):is(.is-published) *) {
    display: block;
  }
}

这里使用的就是group-* 变体

为了更易于控制,您可以使用 & 字符来标记 .group 相对于您传入的选择器在最终选择器中应结束的位置

html
<div class="group">
  <div class="group-[:nth-of-type(3)_&]:block">
    <!-- ... -->
  </div>
</div>

生成的CSS:

css
.group-[:nth-of-type(3)&]:block {
  &:is(:nth-of-type(3) :where(.group) *) {
    display: block;
  }
}
原来的选择器里有一个 *,表示要匹配 .group 的后代里的任意元素。
class中当前元素 & 代表的是::where(.group) *

&:is(...)

这里的 & 再次指向当前元素,Tailwind 用 :is() 包起来,保证能在一个组合器里同时检查父级和自身条件。

:is(:nth-of-type(3) :where(.group) *)

这是关键部分,等价于:

  • :nth-of-type(3) → 当前元素是同类中的第 3 个
  • :where(.group) * → 当前元素必须位于 .group 的后代

合起来: 当前元素必须是 .group 里面的第 3 个同类型元素,才会应用 display: block

选择器匹配的目标是谁?

is(...) 是个伪类,它最终还是匹配“当前元素”。 括号里的东西只是“条件”,只有当当前元素满足这个复合选择器时才算匹配。

也就是说: :is(A B C) 只有在“当前元素能被 A B C 选中”时才成立。


左到右匹配过程

:nth-of-type(3) :where(.group) * 为例:

  • :nth-of-type(3) 找到父级里的第 3 个同类型元素,匹配到它
  • 空格 → 进入后代选择器
  • :where(.group) 在第 3 个元素的后代里找所有 .group
  • 空格 → 再次进入后代选择器
  • \*.group 的后代里的所有元素

最终的“当前元素”是那个 * 匹配到的元素。


所以,它的逻辑是:

当前元素必须是某个第 3 个同类型元素的后代,且必须在 .group 里面,才会被选中。

隐式组

in-* 变体的工作方式与 group 类似,只是您不需要将 group 添加到父元素

html
<!-- group-* 变体写法-->
<div tabindex="0" class="group">
  <div class="opacity-50 group-focus:opacity-100">
<!-- in-* 变体写法-->
<div tabindex="0">
  <div class="opacity-50 in-focus:opacity-100">
    <!-- ... -->
  </div>
</div>

in-* 变体响应任何父级中的状态更改,因此如果您想要更精细的控制,则需要改用 group

基于同级状态设置样式

当您需要根据同级元素的状态设置元素的样式时,请将同级元素标记为 peer 类,并使用 peer-* 变体(例如 peer-invalid)来设置目标元素的样式

html
<form>
  <label class="block">
    <span class="...">Email</span>
    <input type="email" class="peer ..." />
    <p class="invisible peer-invalid:visible ...">Please provide a valid email address.</p>
  </label>
</form>

这使得实现各种巧妙的技巧成为可能,例如浮动标签,而无需任何 JS。

此模式适用于每个伪类变体,例如 peer-focuspeer-requiredpeer-disabled

重要的是要注意,由于 CSS 中后续兄弟选择器的工作方式,peer 标记只能用于之前的兄弟元素

下面的方式,将不起作用,只有之前的兄弟元素可以标记为同级元素

html
<label>
  <span class="peer-invalid:text-red-500 ...">Email</span>
  <input type="email" class="peer ..." />
</label>
区分同级元素

当使用多个同级元素时,您可以通过使用 peer/{name} 类为该同级元素指定唯一的名称,并使用诸如 peer-checked/{name} 之类的类将该名称包含在变体中,从而根据特定同级元素的状态设置某些内容的样式

html
<fieldset>
  <legend>Published status</legend>
  <input id="draft" class="peer/draft" type="radio" name="status" checked />
  <label for="draft" class="peer-checked/draft:text-sky-500">Draft</label>
  <input id="published" class="peer/published" type="radio" name="status" />
  <label for="published" class="peer-checked/published:text-sky-500">Published</label>
  <div class="hidden peer-checked/draft:block">Drafts are only visible to administrators.</div>
  <div class="hidden peer-checked/published:block">Your post will be publicly visible on your site.</div>
</fieldset>
任意同级元素

您可以通过在方括号之间提供您自己的选择器作为任意值来动态创建一次性 peer-* 变体

css
<form>
  <label for="email">Email:</label>
  <input id="email" name="email" type="email" class="is-dirty peer" required />
  <div class="peer-[.is-dirty]:peer-required:block hidden">This field is required.</div>
  <!-- ... -->
</form>

生成的css

css
.peer-[.is-dirty]:peer-required:block {
  &:is(:where(.peer):is(.is-dirty) ~ *) {
    &:is(:where(.peer):required ~ *) {
      display: block;
    }
  }
}

为了更易于控制,您可以使用 & 字符来标记 .peer 相对于您传入的选择器在最终选择器中应结束的位置

html
<div>
  <input type="text" class="peer" />
  <div class="hidden peer-[:nth-of-type(3)_&]:block">
    <!-- ... -->
  </div>
</div>

生成的CSS

css
.peer-[:nth-of-type\(3)_&]:block {
  &:is(:nth-of-type(3) :where(.peer) ~ *) {
    display: block;
  }
}
/*
    ~ 是通用兄弟选择器
	分析一下哈,:where(.peer) ~ *这应该就是当前元素,:nth-of-type(3)就是对当前元素的祖宗进行约束,祖宗得是第三个,当前元素得是.peer元素的兄弟
*/

验证猜想:

html
<div class="main">
    <div></div>
    <div></div>
    <!-- 祖宗元素是第三个 -->
    <div>
        <div class="peer"></div>
        <!--显示成功!!!-->
        <div class="hidden peer-[:nth-of-type(3)_&]:block">第三个元素</div>
    </div>
    <div></div>
</div>

::before 和 ::after

使用 beforeafter 变体设置 ::before::after 伪元素的样式

<label>
  <span class="text-gray-700 after:ml-0.5 after:text-red-500 after:content-['*'] ...">Email</span>
  <input type="email" name="email" class="..." placeholder="you@example.com" />
</label>

呈现的效果:

image-20250920195352062

就是后面的那个*

当使用这些变体时,Tailwind 将默认自动添加 content: '',因此除非您想要不同的值,否则无需指定它

html
<blockquote class="text-center text-2xl font-semibold text-gray-900 italic dark:text-white">
  When you look
  <span class="relative inline-block before:absolute before:-inset-1 before:block before:-skew-y-3 before:bg-pink-500">
    <span class="relative text-white dark:text-gray-950">annoyed</span>
  </span>
  all the time, people think that you're busy.
</blockquote>

值得注意的是,在 Tailwind 项目中,您实际上不需要 ::before::after 伪元素来完成大多数事情 — 通常只需使用真实的 HTML 元素即可。

例如,这是上面相同的设计,但使用 <span> 而不是 ::before 伪元素,这更容易阅读,而且实际上代码更少

html
<blockquote class="text-center text-2xl font-semibold text-gray-900 italic">
  When you look
  <span class="relative">
    <span class="absolute -inset-1 block -skew-y-3 bg-pink-500" aria-hidden="true"></span>
    <span class="relative text-white">annoyed</span>
  </span>
  all the time, people think that you're busy.
</blockquote>

image-20250920200641121

::placeholder

使用 placeholder 变体设置任何输入或 textarea 的占位符文本的样式

<input
  class="placeholder:text-gray-500 placeholder:italic ..."
  placeholder="Search for anything..."
  type="text"
  name="search"
/>

::file

使用 file 变体设置文件输入中按钮的样式

html
<input
  type="file"
  class="file:mr-4 file:rounded-full file:border-0 file:bg-violet-50 file:px-4 file:py-2 file:text-sm file:font-semibold file:text-violet-700 hover:file:bg-violet-100 dark:file:bg-violet-600 dark:file:text-violet-100 dark:hover:file:bg-violet-500 ..."
/>

image-20250920200939954

::marker

使用 marker 变体设置列表中计数器或项目符号的样式

<ul role="list" class="list-disc marker:text-sky-400 ...">
  <li>5 cups chopped Porcini mushrooms</li>
  <li>1/2 cup of olive oil</li>
  <li>3lb of celery</li>
</ul>

image-20250920201402882

::selection

使用 selection 变体设置活动文本选择的样式

html
<div class="selection:bg-fuchsia-300 selection:text-fuchsia-900">
  <p>
    So I started to walk into the water. I won't lie to you boys, I was terrified. But I pressed on, and as I made my
    way past the breakers a strange calm came over me. I don't know if it was divine intervention or the kinship of all
    living things but I tell you Jerry at that moment, I <em>was</em> a marine biologist.
  </p>
</div>

image-20250920202143558

我们已将 selection 变体设计为可继承的,因此您可以将其添加到树中的任何位置,它将应用于所有后代元素。

这使得您可以轻松地将选择颜色设置为与您整个网站的品牌颜色相匹配

::first-line 和 ::first-letter

使用 first-line 变体设置内容块中第一行的样式,并使用 first-letter 变体设置第一个字母的样式

html
<div class="text-gray-700">
  <p
    class="first-letter:float-left first-letter:mr-3 first-letter:text-7xl first-letter:font-bold first-letter:text-gray-900 first-line:tracking-widest first-line:uppercase"
  >
    Well, let me tell you something, funny boy. Y'know that little stamp, the one that says "New York Public Library"?
  </p>
  <p class="mt-6">Well that may not mean anything to you, but that means a lot to me. One whole hell of a lot.</p>
</div>

image-20250920202314178

::backdrop

使用 backdrop 变体设置原生 <dialog> 元素的背景幕的样式

html
<dialog class="backdrop:bg-gray-50">
  <form method="dialog">
    <!-- ... -->
  </form>
</dialog>
<script>
export default {
  mounted() {
    const dialog = document.getElementById("myDialog");
    const openBtn = document.getElementById("openBtn");
    openBtn.addEventListener("click", () => dialog.showModal());
    dialog.addEventListener("close", () => {
      console.log("用户选择:", dialog.returnValue);
    });
  },
};
</script>

如果您在项目中使用原生 <dialog> 元素,您可能还想阅读有关使用 open 变体styling open/closed states的信息。

响应式断点

要在特定断点处设置元素样式,请使用响应式变体,例如 mdlg

例如,这将在移动设备上呈现 3 列网格,在中等宽度屏幕上呈现 4 列网格,在大型宽度屏幕上呈现 6 列网格

html
<div class="grid grid-cols-3 md:grid-cols-4 lg:grid-cols-6">
  <!-- ... -->
</div>

要根据父元素的宽度而不是视口宽度设置元素的样式,请使用 @md@lg 等变体

html
<div class="@container">
  <div class="flex flex-col @md:flex-row">
    <!-- ... -->
  </div>
</div>

查看响应式设计文档,深入了解这些功能的工作原理。

prefers-color-scheme

prefers-color-scheme 媒体查询告诉您用户是喜欢浅色主题还是深色主题,通常在操作系统级别配置

使用没有变体的来定位浅色模式,并使用 dark 变体来为深色模式提供覆盖

html
<div class="bg-white dark:bg-gray-900 ...">
  <!-- ... -->
  <h3 class="text-gray-900 dark:text-white ...">Writes upside-down</h3>
  <p class="text-gray-500 dark:text-gray-400 ...">
    The Zero Gravity Pen can be used to write in any orientation, including upside-down. It even works in outer space.
  </p>
</div>

image-20250920203153640

查看暗黑模式文档,深入了解此功能的工作原理。

prefers-reduced-motion

prefers-reduced-motion 媒体查询告诉您用户是否请求您最小化非必要的运动。

prefers-reduced-motion: reduce,来测试页面在“减少动效”的情况下会如何表现。

当用户请求“减少动效”时,使用 motion-reduce 变体有条件地添加样式

html
<button type="button" class="bg-indigo-500 ..." disabled>
  <svg class="animate-spin motion-reduce:hidden ..." viewBox="0 0 24 24"><!-- ... --></svg>
  Processing...
</button>

prefers-contrast

prefers-contrast 媒体查询告诉您用户是否请求更多或更少的对比度。

当用户请求更高对比度时,使用 contrast-more 变体有条件地添加样式

forced-colors

forced-colors 媒体查询指示用户是否正在使用强制颜色模式。这些模式使用用户定义的调色板覆盖您网站的颜色,用于文本、背景、链接和按钮。

当用户启用强制颜色模式时,使用 forced-colors 变体有条件地添加样式

当用户使用强制颜色模式时,使用 not-forced-colors 变体应用样式

<div class="not-forced-colors:appearance-none ...">
  <!-- ... -->
</div>

Tailwind 还包括强制颜色调整实用程序,用于选择加入和退出强制颜色。

inverted-colors

当用户启用反转颜色方案时,使用 inverted-colors 变体有条件地添加样式

pointer 和 any-pointer

pointer 媒体查询告诉您用户是否拥有主要指点设备(如鼠标)以及该指点设备的精度。

使用 pointer-fine 变体来定位精确的指点设备(如鼠标或触控板),或使用 pointer-coarse 变体来定位不太精确的指点设备(如触摸屏),这对于在触摸设备上提供更大的点击目标非常有用

orientation

当视口处于特定方向时,使用 portraitlandscape 变体有条件地添加样式

scripting

使用 noscript 变体根据用户是否启用了脚本(例如 JavaScript)有条件地添加样式

print

使用 print 变体有条件地添加仅在打印文档时应用的样式

@supports

使用 supports-[...] 变体根据用户的浏览器是否支持特定功能来设置样式

html
<div class="flex supports-[display:grid]:grid ...">
  <!-- ... -->
</div>

在底层,supports-[...] 变体生成@supports 规则,并在方括号之间接受您将与 @supports (...) 一起使用的任何内容,例如属性/值对,甚至使用 andor 的表达式。

为了简洁起见,如果您只需要检查是否支持某个属性(而不是特定值),则只需指定属性名称即可

html
<div class="bg-black/75 supports-backdrop-filter:bg-black/25 supports-backdrop-filter:backdrop-blur ...">
  <!-- ... -->
</div>

使用 not-supports-[...] 变体根据用户的浏览器是否不支持特定功能来设置样式

html
<div class="not-supports-[display:grid]:flex">
  <!-- ... -->
</div>

@starting-style

使用 starting 变体来设置元素在 DOM 中首次呈现时的外观,或从 display: none 过渡到可见时的外观

html
<div>
  <button popovertarget="my-popover">Check for updates</button>
  <div popover id="my-popover" class="opacity-0 starting:open:opacity-0 ...">
    <!-- ... -->
  </div>
</div>

属性选择器

ARIA 状态

使用 aria-* 变体根据ARIA 属性有条件地设置样式。

ARIA 属性用于修改无障碍树中定义的元素的状态和属性。

ARIA 仅用于修改无障碍树,进而改变辅助技术向用户呈现内容的方式。ARIA 不会改变元素的功能或行为。当使用非语义化的 HTML 元素来实现其他功能时,你必须使用 JavaScript 来控制元素的实际行为、焦点以及 ARIA 状态。

例如,要在 aria-checked 属性设置为 true 时应用 bg-sky-700 类,请使用 aria-checked:bg-sky-700

html
<div aria-checked="true" class="bg-gray-600 aria-checked:bg-sky-700">
  <!-- ... -->
</div>

默认情况下,我们包含了最常见的布尔 ARIA 属性的变体

变体CSS
aria-busy&[aria-busy="true"]
aria-checked&[aria-checked="true"]
aria-disabled&[aria-disabled="true"]
aria-expanded&[aria-expanded="true"]
aria-hidden&[aria-hidden="true"]
aria-pressed&[aria-pressed="true"]
aria-readonly&[aria-readonly="true"]
aria-required&[aria-required="true"]
aria-selected&[aria-selected="true"]

您可以通过创建新的变体来自定义哪些 aria-* 变体可用

@custom-variant aria-asc (&[aria-sort="ascending"]);
@custom-variant aria-desc (&[aria-sort="descending"]);

如果您需要使用不适合包含在项目中的一次性 aria 变体,或者对于需要特定值的更复杂的 ARIA 属性,请使用方括号来动态生成具有任意值的属性

html
<table>
  <thead>
    <tr>
      <th
        aria-sort="ascending"
        class="aria-[sort=ascending]:bg-[url('/img/down-arrow.svg')] aria-[sort=descending]:bg-[url('/img/up-arrow.svg')]"
      >
        Invoice #
      </th>
      <!-- ... -->
    </tr>
  </thead>
  <!-- ... -->
</table>

ARIA 状态变体还可以使用 group-aria-*peer-aria-* 变体来定位父元素和兄弟元素

html
<table>
  <thead>
    <tr>
    <th aria-sort="ascending" class="group">
      Invoice #
      <svg class="group-aria-[sort=ascending]:rotate-0 group-aria-[sort=descending]:rotate-180"><!-- ... --></svg>
    </th>
    <!-- ... -->
    </tr>
  </thead>
  <!-- ... -->
</table>
Data attributes

使用 data-* 变体根据 data 属性有条件地应用样式。

要检查 data 属性是否存在(而不是特定值),您只需指定属性名称

html
<!-- Will apply -->
<div data-active class="border border-gray-300 data-active:border-purple-500">
  <!-- ... -->
</div>

<!-- Will not apply -->
<div class="border border-gray-300 data-active:border-purple-500">
  <!-- ... -->
</div>

如果您需要检查特定值,则可以使用任意值

html
<!-- Will apply -->
<div data-size="large" class="data-[size=large]:p-8">
  <!-- ... -->
</div>

<!-- Will not apply -->
<div data-size="medium" class="data-[size=large]:p-8">
  <!-- ... -->
</div>

或者,您可以通过在 data-* 命名空间中创建新变体,为您项目中常用的 data 属性配置快捷方式

app.css

css
@import "tailwindcss";

@custom-variant data-checked (&[data-ui~="checked"]);

然后您可以在项目中使用这些自定义的 data-* 变体

html
<div data-ui="checked active" class="data-checked:underline">
  <!-- ... -->
</div>
RTL 支持

在构建多方向布局时,分别使用 rtlltr 变体在从右到左和从左到右模式下有条件地添加样式

image-20250921002056365

html
<div class="group flex items-center">
  <img class="h-12 w-12 shrink-0 rounded-full" src="..." alt="" />
  <div class="ltr:ml-3 rtl:mr-3">
    <p class="text-gray-700 group-hover:text-gray-900 ...">...</p>
    <p class="text-gray-500 group-hover:text-gray-700 ...">...</p>
  </div>
</div>

请记住,这些变体仅在您构建需要支持从左到右从右到左布局的站点时才有用。如果您构建的站点只需要支持单个方向,则不需要这些变体 — 只需应用对您的内容有意义的样式即可。

打开/关闭状态

<details><dialog> 元素处于打开状态时,使用 open 变体有条件地添加样式

html
<details class="border border-transparent open:border-black/10 open:bg-gray-100 ..." open>
  <summary class="text-sm leading-6 font-semibold text-gray-900 select-none">Why do they call it Ovaltine?</summary>
  <div class="mt-3 text-sm leading-6 text-gray-600">
    <p>The mug is round. The jar is round. They should call it Roundtine.</p>
  </div>
</details>

关闭状态

image-20250921002401235

打开状态

image-20250921002429047

此变体还针对 popover 的 :popover-open 伪类

html
<div>
  <button popovertarget="my-popover">Open Popover</button>
  <div popover id="my-popover" class="opacity-0 open:opacity-100 ...">
    <!-- ... -->
  </div>
</div>
样式化 inert 元素

inert 变体允许您样式化标记有 inert 属性的元素

html
<form>
  <legend>Notification preferences</legend>
  <fieldset>
    <input type="radio" />
    <label> Custom </label>
    <fieldset inert class="inert:opacity-50">
      <!-- ... -->
    </fieldset>
    <input type="radio" />
    <label> Everything </label>
  </fieldset>
</form>

这对于添加视觉提示非常有用,这些提示可以清楚地表明内容部分不是交互式的。

inert 是一个 原生有用的 HTML 属性,而且越来越多浏览器已经支持。

它的作用:

让一个元素和它的子元素完全不可交互,也不会被聚焦或读屏软件访问。

子选择器

样式化直接子元素

虽然通常最好将实用程序类直接放在子元素上,但在您需要样式化您无法控制的直接子元素的情况下,可以使用 * 变体

image-20250921003549070

html
<div>
  <h2>Categories<h2>
  <ul class="*:rounded-full *:border *:border-sky-100 *:bg-sky-50 *:px-2 *:py-0.5 dark:text-sky-300 dark:*:border-sky-500/15 dark:*:bg-sky-500/10 ...">
    <li>Sales</li>
    <li>Marketing</li>
    <li>SEO</li>
    <!-- ... -->
  </ul>
</div>

重要的是要注意,由于生成的子选择器的特殊性,直接在子元素本身上使用实用程序覆盖样式将不起作用

下面不起作用,子元素无法覆盖自己的样式。

html
<ul class="*:bg-sky-50 ...">
  <li class="bg-red-50 ...">Sales</li>
  <li>Marketing</li>
  <li>SEO</li>
  <!-- ... -->
</ul>
样式化所有后代元素

* 类似,** 变体可用于样式化元素的子元素。 主要区别在于 ** 将样式应用于所有后代元素,而不仅仅是直接子元素。 当您将其与另一个变体结合使用以缩小您要选择的内容范围时,这尤其有用

image-20250921003739478

html
<ul class="**:data-avatar:size-12 **:data-avatar:rounded-full ...">
  {#each items as item}
    <li>
      <img src={item.src} data-avatar />
      <p>{item.name}</p>
    </li>
  {/each}
</ul>

自定义变体

使用任意变体

就像任意值让您可以在实用程序类中使用自定义值一样,任意变体让您可以直接在 HTML 中编写自定义选择器变体。

任意变体只是表示选择器的格式字符串,用方括号括起来。 例如,当元素具有 is-dragging 类时,此任意变体会将光标更改为 grabbing

html
<ul role="list">
  {#each items as item}
    <li class="[&.is-dragging]:cursor-grabbing">{item}</li>
  {/each}
</ul>

生成的CSS

css
.[&.is-dragging]:cursor-grabbing {
  &.is-dragging {
    cursor: grabbing;
  }
}

任意变体可以像 Tailwind 中的其余变体一样,与内置变体或彼此堆叠

html
<ul role="list">
  {#each items as item}
    <li class="[&.is-dragging]:active:cursor-grabbing">{item}</li>
  {/each}
</ul>

CSS

css
.[&.is-dragging]:active:cursor-grabbing {
  &.is-dragging {
    &:active {
      cursor: grabbing;
    }
  }
}

如果您的选择器中需要空格,可以使用下划线。 例如,此任意变体选择您添加类的元素内的所有 p 元素

html
<div class="[&_p]:mt-4">
  <p>Lorem ipsum...</p>
  <ul>
    <li>
      <p>Lorem ipsum...</p>
    </li>
    <!-- ... -->
  </ul>
</div>

CSS

css
.[&_p]:mt-4 {
  & p {
    margin-top: calc(var(--spacing) * 4);
  }
}

您还可以在任意变体中使用 at-rules,如 @media@supports

html
<div class="flex [@supports(display:grid)]:grid">
  <!-- ... -->
</div>

使用 at-rule 自定义变体时,& 占位符不是必需的,就像使用预处理器进行嵌套时一样。

注册自定义变体

如果您发现自己在项目中多次使用相同的任意变体,则可能值得使用 @custom-variant 指令创建自定义变体

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

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

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

添加自定义变体文档中了解有关添加自定义变体的更多信息。

响应式设计

使用响应式布局标识符(responsive modifiers)构建完全支持响应式布局的用户界面,以适应任何大小的 屏幕。

Tailwind-响应式设计.md

夜间模式(Dark Mode)

通过在 HTML 代码中添加夜间模式标识符(dark mode modifier)直接让你的网站支持夜间模式。

Tailwind-暗黑模式.md

主题变量

Tailwind-主题变量.md

颜色

Tailwind-颜色.md

添加自定义样式

Tailwind-添加自定义样式.md

在源文件中检测类名

Tailwind-扫描原理.md

函数和指令

Tailwind-函数和指令.md

样式

https://tailwind.org.cn/docs/preflight

https://tailwindcss.com/docs/

评论

评论加载中……