入门
将你的 Tailwind CSS 项目从 v3 升级到 v4。
Tailwind CSS v4.0 是框架的一个新主版本,虽然我们已尽力减少破坏性变更,但仍有一些必要的更新。本指南概述了将项目从 v3 升级到 v4 所需的所有步骤。
Tailwind CSS v4.0 专为 Safari 16.4+、Chrome 111+ 和 Firefox 128+ 设计。 如果你需要支持旧版浏览器,请继续使用 v3.4,直到你的浏览器支持需求发生变化。
如果你想将项目从 v3 升级到 v4,可以使用我们的升级工具来完成大部分繁重工作:
$ npx @tailwindcss/upgrade
对于大多数项目,升级工具将自动化整个迁移过程,包括更新依赖项、将配置文件迁移到 CSS 以及处理模板文件的所有变更。
升级工具需要 Node.js 20 或更高版本,因此在运行前请确保你的环境已更新。
我们建议在新分支中运行升级工具,然后仔细审查差异并在浏览器中测试你的项目,以确保所有变更看起来都正确。在复杂项目中,你可能需要手动调整一些内容,但无论如何该工具都能为你节省大量时间。
最好也通读 v4 的所有破坏性变更,充分了解有哪些变化,以防项目中还有其他需要更新的内容未被升级工具捕获。
在 v3 版本中,tailwindcss
包是一个 PostCSS 插件,但在 v4 中 PostCSS 插件已移至专门的 @tailwindcss/postcss
包中。
此外,v4 版本现在会自动处理导入和供应商前缀,因此如果你的项目中包含以下插件可以移除它们:
export default { plugins: { "postcss-import": {}, tailwindcss: {}, autoprefixer: {}, "@tailwindcss/postcss": {}, },};
如果你正在使用 Vite,我们建议从 PostCSS 插件迁移到我们新的专用 Vite 插件,以获得更好的性能和最佳开发者体验:
import { defineConfig } from "vite";import tailwindcss from "@tailwindcss/vite";export default defineConfig({ plugins: [ tailwindcss(), ],});
在 v4 版本中,Tailwind CLI 已移至专门的 @tailwindcss/cli
包中。请更新你的构建命令以使用新包:
npx tailwindcss -i input.css -o output.cssnpx @tailwindcss/cli -i input.css -o output.css
以下是 Tailwind CSS v4.0 中所有破坏性变更的完整列表。
我们的升级工具会自动处理大部分变更,因此我们强烈建议尽可能使用它。
Tailwind CSS v4.0 专为现代浏览器设计,支持 Safari 16.4、Chrome 111 和 Firefox 128。我们依赖现代 CSS 特性如 @property
和 color-mix()
来实现核心框架功能,因此 Tailwind CSS v4.0 无法在旧版浏览器中运行。
如需支持旧版浏览器,我们建议暂时继续使用 v3.4 版本。我们正在积极开发兼容模式以帮助用户更快升级,未来将分享更多相关信息。
在 v4 版本中,您需要使用常规 CSS 的 @import
语句来导入 Tailwind,而不是 v3 中的 @tailwind
指令:
@tailwind base;@tailwind components;@tailwind utilities;@import "tailwindcss";
我们移除了所有在 v3 版本中已废弃且多年未在文档中提及的工具类。以下是已移除的工具类及其现代替代方案的列表:
已废弃 | 替代方案 |
---|---|
bg-opacity-* | 使用透明度修饰符如 bg-black/50 |
text-opacity-* | 使用透明度修饰符如 text-black/50 |
border-opacity-* | 使用透明度修饰符如 border-black/50 |
divide-opacity-* | 使用透明度修饰符如 divide-black/50 |
ring-opacity-* | 使用透明度修饰符如 ring-black/50 |
placeholder-opacity-* | 使用透明度修饰符如 placeholder-black/50 |
flex-shrink-* | shrink-* |
flex-grow-* | grow-* |
overflow-ellipsis | text-ellipsis |
decoration-slice | box-decoration-slice |
decoration-clone | box-decoration-clone |
在 v4 版本中,我们重命名了以下工具类,使其更加一致和可预测:
v3 | v4 |
---|---|
shadow-sm | shadow-xs |
shadow | shadow-sm |
drop-shadow-sm | drop-shadow-xs |
drop-shadow | drop-shadow-sm |
blur-sm | blur-xs |
blur | blur-sm |
backdrop-blur-sm | backdrop-blur-xs |
backdrop-blur | backdrop-blur-sm |
rounded-sm | rounded-xs |
rounded | rounded-sm |
outline-none | outline-hidden |
ring | ring-3 |
我们重命名了默认的阴影、圆角和模糊尺寸标准,以确保每个工具类都有对应的命名值。为了向后兼容,"裸"版本仍然可用,但除非更新为对应的 xs
版本,否则 sm
工具类会显示不同的效果。
要将项目更新以适应这些变化,请将所有 v3 版本的工具类替换为 v4 版本:
<input class="shadow-sm" /><input class="shadow-xs" /><input class="shadow" /><input class="shadow-sm" />
outline
工具类现在默认设置 outline-width: 1px
,以与边框和环形工具类保持一致。此外,所有 outline-<number>
工具类默认将 outline-style
设为 solid
,无需再与 outline
组合使用:
<input class="outline outline-2" /><input class="outline-2" />
原先的 outline-none
工具类实际上并未设置 outline-style: none
,而是设置了一个不可见的轮廓,出于无障碍考虑在强制颜色模式下仍会显示。
为了更清晰地表达这一点,我们将其重命名为 outline-hidden
,并新增了一个真正设置 outline-style: none
的 outline-none
工具类。
要将项目更新以适应这一变化,请将所有 outline-none
替换为 outline-hidden
:
<input class="focus:outline-none" /><input class="focus:outline-hidden" />
在 v3 版本中,ring
工具类会添加 3px
的描边。我们在 v4 版本中将其改为 1px
,以保持与边框(border)和轮廓(outline)的一致性。
要更新你的项目以适应此变更,请将所有 ring
的使用替换为 ring-3
:
<input class="ring ring-blue-500" /><input class="ring-3 ring-blue-500" />
我们修改了 space-x-*
和 space-y-*
工具类 使用的选择器,以解决大型页面上的严重性能问题:
/* 之前 */.space-y-4 > :not([hidden]) ~ :not([hidden]) { margin-top: 1rem;}/* 现在 */.space-y-4 > :not(:last-child) { margin-bottom: 1rem;}
如果你曾经将这些工具类与行内元素一起使用,或者通过为子元素添加其他边距来调整间距,可能会在项目中看到变化。
如果此变更导致你的项目出现问题,我们建议迁移到 flex 或 grid 布局并使用 gap
替代:
<div class="space-y-4 p-4"><div class="flex flex-col gap-4 p-4"> <label for="name">Name</label> <input type="text" name="name" /></div>
在 v3 版本中,使用变体覆盖渐变的一部分会"重置"整个渐变,因此在这个例子中,to-*
颜色在暗黑模式下会变成透明而不是黄色:
<div class="bg-gradient-to-r from-red-500 to-yellow-400 dark:from-blue-500"> <!-- ... --></div>
在 v4 版本中,这些值会被保留,这与 Tailwind 中其他工具类的工作方式更加一致。
这意味着如果你想要在特定状态下将三色渐变"取消设置"回双色渐变,可能需要显式使用 via-none
:
<div class="bg-linear-to-r from-red-500 via-orange-400 to-yellow-400 dark:via-none dark:from-blue-500 dark:to-teal-400"> <!-- ... --></div>
在 v3 版本中,container
工具类有几个配置选项如 center
和 padding
,这些在 v4 中已不再存在。
要在 v4 中自定义 container
工具类,可以使用 @utility
指令进行扩展:
@utility container { margin-inline: auto; padding-inline: 2rem;}
在 v3 版本中,border-*
和 divide-*
工具类默认使用你配置的 gray-200
颜色。我们在 v4 中将其改为 currentColor
,使 Tailwind 更少主观性并匹配浏览器默认值。
要为这个变更更新你的项目,请确保在使用 border-*
或 divide-*
工具类时指定颜色:
<div class="border border-gray-200 px-2 py-3 ..."> <!-- ... --></div>
或者,将这些基础样式添加到你的项目中以保留 v3 的行为:
@layer base { *, ::after, ::before, ::backdrop, ::file-selector-button { border-color: var(--color-gray-200, currentColor); }}
我们将 ring
工具类的宽度从 3px 改为 1px,并将默认颜色从 blue-500
改为 currentColor
,以使其与 border-*
、divide-*
和 outline-*
工具类更加一致。
要更新你的项目以适应这些变化,请将所有使用 ring
的地方替换为 ring-3
:
<button class="focus:ring ..."><button class="focus:ring-3 ..."> <!-- ... --></button>
然后确保在所有依赖默认环颜色的地方添加 ring-blue-500
:
<button class="focus:ring-3 focus:ring-blue-500 ..."> <!-- ... --></button>
或者,将这些主题变量添加到你的 CSS 中以保留 v3 的行为:
@theme { --default-ring-width: 3px; --default-ring-color: var(--color-blue-500);}
不过请注意,这些变量仅出于兼容性原因而支持,并不被视为 Tailwind CSS v4.0 的惯用用法。
我们在 v4 中对 Preflight 的基础样式做了一些小改动:
在 v3 中,占位符文本默认使用你配置的 gray-400
颜色。在 v4 中,我们简化为直接使用当前文本颜色,透明度为 50%。
你可能甚至不会注意到这个变化(它甚至可能让你的项目看起来更好),但如果你想保留 v3 的行为,请将以下 CSS 添加到你的项目中:
@layer base { input::placeholder, textarea::placeholder { color: var(--color-gray-400); }}
现在按钮使用 cursor: default
而非 cursor: pointer
,以匹配浏览器的默认行为。
如果你想继续保持默认使用 cursor: pointer
,请将这些基础样式添加到你的 CSS 中:
@layer base { button:not(:disabled), [role="button"]:not(:disabled) { cursor: pointer; }}
Preflight 现在重置了 <dialog>
元素的边距,以与其他元素的重置方式保持一致。
如果你仍然希望对话框默认居中,请将此 CSS 添加到你的项目中:
@layer base { dialog { margin: auto; }}
前缀现在看起来像变体,并且始终位于类名的开头:
<div class="tw:flex tw:bg-red-500 tw:hover:bg-red-600"> <!-- ... --></div>
使用前缀时,你仍应像不使用前缀一样配置主题变量:
@import "tailwindcss" prefix(tw);@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); /* ... */}
生成的 CSS 变量 会 包含前缀,以避免与项目中任何现有变量冲突:
:root { --tw-font-display: "Satoshi", "sans-serif"; --tw-breakpoint-3xl: 120rem; --tw-color-avocado-100: oklch(0.99 0 0); --tw-color-avocado-200: oklch(0.98 0.04 113.22); --tw-color-avocado-300: oklch(0.94 0.11 115.03); /* ... */}
在 v3 版本中,任何在 @layer utilities
或 @layer components
中定义的自定义类都会被 Tailwind 识别为真正的工具类,并能自动与 hover
、focus
或 lg
等变体配合使用,区别在于 @layer components
中的类总是会优先出现在生成的样式表中。
在 v4 版本中,我们使用原生的级联层(cascade layers)并不再劫持 @layer
规则,因此引入了 @utility
API 作为替代方案:
@layer utilities { .tab-4 { tab-size: 4; }}@utility tab-4 { tab-size: 4;}
现在自定义工具类还会根据它们定义的属性数量进行排序。这意味着像这样的 .btn
组件工具类可以被其他 Tailwind 工具类覆盖,而无需额外配置:
@layer components { .btn { border-radius: 0.5rem; padding: 0.5rem 1rem; background-color: ButtonFace; }}@utility btn { border-radius: 0.5rem; padding: 0.5rem 1rem; background-color: ButtonFace;}
了解更多关于注册自定义工具类的信息,请参阅添加自定义工具类文档。
在 v3 版本中,堆叠变体是从右向左应用的,但在 v4 中我们已将其更新为从左向右应用,使其更接近 CSS 语法。
要为这一变更更新你的项目,请反转项目中所有对顺序敏感的堆叠变体的顺序:
<ul class="py-4 first:*:pt-0 last:*:pb-0"><ul class="py-4 *:first:pt-0 *:last:pb-0"> <li>One</li> <li>Two</li> <li>Three</li></ul>
这种情况在你的项目中可能很少见——直接子元素变体(*
)和任何排版插件变体(prose-headings
)是你最可能使用的变体,而且即使如此,也只有在它们与其他变体堆叠使用时才会涉及。
在 v3 中,你可以不使用 var()
就能将 CSS 变量作为任意值使用,但 CSS 的最新更新意味着这常常会产生歧义,因此我们在 v4 中更改了这一语法,改用圆括号而非方括号。
要为这一变更更新你的项目,请将旧的变量简写语法替换为新的变量简写语法:
<div class="bg-[--brand-color]"></div><div class="bg-(--brand-color)"></div>
在 v4 版本中,我们更新了 hover
变体,使其仅在主输入设备支持悬停时生效:
@media (hover: hover) { .hover\:underline:hover { text-decoration: underline; }}
如果您构建的网站依赖触摸设备通过点击触发悬停效果,这可能会造成问题。如果这对您是个问题,您可以用旧的实现方式覆盖 hover
变体:
@custom-variant hover (&:hover);
不过我们通常建议将悬停功能视为增强体验,不要依赖它来实现网站功能,因为触摸设备实际上并不具备悬停能力。
transition
和 transition-color
工具类现在包含 outline-color
属性。
这意味着如果您在聚焦时添加了自定义颜色的轮廓,您会看到颜色从默认颜色过渡的效果。要避免这种情况,请确保无条件设置轮廓颜色,或为两种状态都明确设置:
<button class="transition hover:outline-2 hover:outline-cyan-500"></button><button class="outline-cyan-500 transition hover:outline-2"></button>
在 v3 版本中,您可以使用 corePlugins
选项来完全禁用框架中的某些工具类。v4 版本不再支持此功能。
由于 v4 版本为所有主题值提供了 CSS 变量,我们建议尽可能使用这些变量而非 theme()
函数:
.my-class { background-color: theme(colors.red.500); background-color: var(--color-red-500);}
对于仍需使用 theme()
函数的场景(例如不支持 CSS 变量的媒体查询),应使用 CSS 变量名替代旧的点表示法:
@media (width >= theme(screens.xl)) {@media (width >= theme(--breakpoint-xl)) { /* ... */}
JavaScript 配置文件仍向后兼容,但在 v4 版本中不再自动检测。
如需继续使用 JavaScript 配置文件,可通过 @config
指令显式加载:
@config "../../tailwind.config.js";
v4.0 版本不支持基于 JavaScript 的配置中的 corePlugins
、safelist
和 separator
选项。
在 v3 版本中,我们导出了一个 resolveConfig
函数,你可以用它来将基于 JavaScript 的配置转换为扁平对象,以便在其他 JavaScript 代码中使用。
我们在 v4 版本中移除了这个功能,希望人们可以直接使用我们生成的 CSS 变量,这样更简单且能显著减少打包体积。
例如,流行的 React 动画库 Motion 允许你使用 CSS 变量值进行动画处理:
<motion.div animate={{ backgroundColor: "var(--color-blue-500)" }} />
如果你需要在 JavaScript 中获取解析后的 CSS 变量值,可以使用 getComputedStyle
来获取文档根元素上的主题变量值:
let styles = getComputedStyle(document.documentElement);let shadow = styles.getPropertyValue("--shadow-xl");
在 v4 版本中,与主 CSS 文件分开打包的样式表(例如 CSS 模块文件、Vue/Svelte/Astro 中的 <style>
块等)无法访问其他文件中定义的主题变量、自定义工具类和自定义变体。
为了使这些定义在这些上下文中可用,可以使用 @reference
来导入它们,而不会在打包结果中重复 CSS 代码:
<template> <h1>Hello world!</h1></template><style> @reference "../../app.css"; h1 { @apply text-2xl font-bold text-red-500; }</style>
或者,你也可以直接使用 CSS 主题变量而完全不使用 @apply
,这还能提升性能,因为 Tailwind 不需要处理这些样式:
<template> <h1>Hello world!</h1></template><style> h1 { color: var(--text-red-500); }</style>
你可以在与 CSS 模块一起使用 Tailwind 文档中找到更多相关信息。