Skip to content
全部文档

升级指南

将 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,可以使用我们的升级工具完成绝大部分繁重工作:

Terminal
sh
$ npx @tailwindcss/upgrade

对大多数项目而言,升级工具会自动化整个迁移过程,包括更新依赖、把配置文件迁移到 CSS,以及处理模板文件中的变更。

升级工具需要 Node.js 20 或更高版本,运行前请确保环境已更新。

建议在新分支上运行升级工具,然后仔细审查 diff,并在浏览器中测试项目,确认所有变更看起来都正确。复杂项目可能需要少量手工调整,但无论如何工具都能节省大量时间。

另外最好通读 v4 的全部破坏性变更,弄清改了什么,以防项目中还有升级工具未覆盖、需要你自行更新的地方。

手动升级

使用 PostCSS

在 v3 中,tailwindcss 包本身就是 PostCSS 插件;到了 v4,PostCSS 插件独立到专用的 @tailwindcss/postcss 包中。

此外,v4 会自动处理导入和厂商前缀,因此如果项目里有 postcss-importautoprefixer,可以移除它们:

postcss.config.mjs
js
export default {
  plugins: {
    "postcss-import": {},
    tailwindcss: {},
    autoprefixer: {},
    "@tailwindcss/postcss": {},
  },
};

使用 Vite

如果使用 Vite,建议从 PostCSS 插件迁移到新的专用 Vite 插件,以获得更好的性能和开发体验:

vite.config.ts
ts

export default defineConfig({
  plugins: [
    tailwindcss(),
  ],
});

使用 Tailwind CLI

在 v4 中,Tailwind CLI 位于专用的 @tailwindcss/cli 包。请把构建命令更新为使用这个新包:

Terminal
sh
npx tailwindcss -i input.css -o output.css
npx @tailwindcss/cli -i input.css -o output.css

相对 v3 的变更

以下是 Tailwind CSS v4.0 中全部破坏性变更的完整列表。

我们的升级工具 会自动处理其中大多数变更,因此强烈建议尽可能使用它。

浏览器要求

Tailwind CSS v4.0 面向现代浏览器,目标是 Safari 16.4、Chrome 111 和 Firefox 128。核心框架功能依赖 @propertycolor-mix() 等现代 CSS 特性,因此 Tailwind CSS v4.0 无法在更旧的浏览器中工作。

如果需要支持更旧的浏览器,目前建议继续使用 v3.4。我们正在积极探索兼容模式,以便大家更早升级,后续会分享更多消息。

移除 @tailwind 指令

在 v4 中,使用常规 CSS @import 语句导入 Tailwind,而不再使用 v3 中的 @tailwind 指令:

CSS
css
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "tailwindcss";

移除已弃用的 utility

我们移除了在 v3 中已弃用、并且多年未再写入文档的 utility。下面列出已移除项及其现代替代:

已弃用替代
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-ellipsistext-ellipsis
decoration-slicebox-decoration-slice
decoration-clonebox-decoration-clone

重命名的 utility

为了更一致、更可预期,我们在 v4 中重命名了下列 utility:

v3v4
shadow-smshadow-xs
shadowshadow-sm
drop-shadow-smdrop-shadow-xs
drop-shadowdrop-shadow-sm
blur-smblur-xs
blurblur-sm
backdrop-blur-smbackdrop-blur-xs
backdrop-blurbackdrop-blur-sm
rounded-smrounded-xs
roundedrounded-sm
outline-noneoutline-hidden
ringring-3

更新了 shadow、radius 和 blur 比例

我们重命名了默认的 shadow、radius 和 blur 比例,确保每个 utility 都有命名值。「裸」版本仍可向后兼容,但 <em><utility></em>-sm 这类 utility 看起来会不同,除非更新为对应的 <em><utility></em>-xs 版本。

要适配这些变更,请把所有 v3 utility 替换为对应的 v4 版本:

HTML
html
<input class="shadow-sm" />
<input class="shadow-xs" />

<input class="shadow" />
<input class="shadow-sm" />

重命名了 outline utility

outline utility 现在默认设置 outline-width: 1px,以便与 border、ring utility 更一致。此外,所有 outline-<number> utility 都会把 outline-style 默认为 solid,无需再与 outline 组合使用:

HTML
html
<input class="outline outline-2" />
<input class="outline-2" />

此前的 outline-none utility 实际上并没有设置 outline-style: none,而是设置了不可见的轮廓,以便在强制颜色模式下仍能显示,满足无障碍需求。

为了更清晰,我们把该 utility 重命名为 outline-hidden,并新增真正设置 outline-style: noneoutline-none utility。

要适配此变更,请把所有 outline-none 替换为 outline-hidden

HTML
html
<input class="focus:outline-none" />
<input class="focus:outline-hidden" />

默认 ring 宽度变更

在 v3 中,ring utility 会添加 3px 的 ring。v4 中改为 1px,以便与 border、outline 保持一致。

要适配此变更,请把所有 ring 替换为 ring-3

HTML
html
<input class="ring ring-blue-500" />
<input class="ring-3 ring-blue-500" />

Space-between 选择器

我们更改了 space-x-*space-y-* utility 使用的选择器,以解决大页面上的严重性能问题:

CSS
css
/* Before */
.space-y-4 > :not([hidden]) ~ :not([hidden]) {
  margin-top: 1rem;
}

/* Now */
.space-y-4 > :not(:last-child) {
  margin-bottom: 1rem;
}

如果你曾把这些 utility 用在行内元素上,或曾给子元素额外加外边距来微调间距,项目中可能会看到变化。

如果此变更在项目中造成问题,建议迁移到 flex 或 grid 布局,改用 gap

HTML
html
<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>

Divide 选择器

我们更改了 divide-x-*divide-y-* utility 使用的选择器,以解决大页面上的严重性能问题:

CSS
css
/* Before */
.divide-y-4 > :not([hidden]) ~ :not([hidden]) {
  border-top-width: 4px;
}

/* Now */
.divide-y-4 > :not(:last-child) {
  border-bottom-width: 4px;
}

如果你曾把这些 utility 用在行内元素上、曾给子元素额外加外边距/内边距来微调间距,或调整过特定子元素的边框,项目中可能会看到变化。

在渐变上使用变体

在 v3 中,用变体覆盖渐变的一部分会「重置」整个渐变,因此这个例子里,深色模式下 to-* 颜色会变成透明而不是黄色:

HTML
html
<!-- [!code classes:dark:from-blue-500] -->
<div class="bg-gradient-to-r from-red-500 to-yellow-400 dark:from-blue-500">
  <!-- ... -->
</div>

在 v4 中,这些值会被保留,这与 Tailwind 中其他 utility 的行为更一致。

这意味着,如果要在特定状态下把三色标渐变「取消」回两色标渐变,可能需要显式使用 via-none

HTML
html
<!-- [!code classes:dark: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>

Container 配置

在 v3 中,container utility 有 centerpadding 等若干配置选项,这些在 v4 中已不存在。

要在 v4 中自定义 container utility,请使用 @utility 指令扩展它:

CSS
css
@utility container {
  margin-inline: auto;
  padding-inline: 2rem;
}

默认边框颜色

在 v3 中,border-*divide-* utility 默认使用你配置的 gray-200 颜色。v4 中改为 currentColor,让 Tailwind 少一些主张,并与浏览器默认值一致。

要适配此变更,请在使用 border-*divide-* utility 的地方都指定颜色:

html
<!-- [!code classes:border-gray-200] -->
<div class="border border-gray-200 px-2 py-3 ...">
  <!-- ... -->
</div>

或者,把这些基础样式加到项目中以保留 v3 行为:

CSS
css
@layer base {
  *,
  ::after,
  ::before,
  ::backdrop,
  ::file-selector-button {
    border-color: var(--color-gray-200, currentColor);
  }
}

默认 ring 宽度和颜色

我们把 ring utility 的宽度从 3px 改为 1px,并把默认颜色从 blue-500 改为 currentColor,以便与 border-*divide-*outline-* utility 更一致。

要适配这些变更,请把所有 ring 替换为 ring-3

html
<!-- prettier-ignore -->
<button class="focus:ring ..."> 
<button class="focus:ring-3 ..."> 
  <!-- ... -->
</button>

然后,在依赖默认 ring 颜色的地方加上 ring-blue-500

html
<!-- [!code classes:focus:ring-blue-500] -->
<button class="focus:ring-3 focus:ring-blue-500 ...">
  <!-- ... -->
</button>

或者,把这些主题变量加到 CSS 中以保留 v3 行为:

CSS
css
@theme {
  --default-ring-width: 3px;
  --default-ring-color: var(--color-blue-500);
}

但请注意,这些变量仅为兼容而支持,并不被视为 Tailwind CSS v4.0 的惯用写法。

Preflight 变更

我们在 v4 中对 Preflight 的基础样式做了几处小改动:

新的默认占位符颜色

在 v3 中,占位符文本默认使用你配置的 gray-400 颜色。v4 中简化为使用当前文本颜色的 50% 不透明度。

你可能根本注意不到这个变化(甚至可能让项目更好看),但如果想保留 v3 行为,把这段 CSS 加到项目中:

CSS
css
@layer base {
  input::placeholder,
  textarea::placeholder {
    color: var(--color-gray-400);
  }
}

按钮使用默认光标

按钮现在使用 cursor: default 而不是 cursor: pointer,以匹配浏览器默认行为。

如果希望默认继续使用 cursor: pointer,把这些基础样式加到 CSS 中:

CSS
css
@layer base {
  button:not(:disabled),
  [role="button"]:not(:disabled) {
    cursor: pointer;
  }
}

移除了 dialog 外边距

Preflight 现在会重置 <dialog> 元素的外边距,与其他元素的重置方式保持一致。

如果仍希望 dialog 默认居中,把这段 CSS 加到项目中:

CSS
css
@layer base {
  dialog {
    margin: auto;
  }
}

hidden 属性优先

blockflex 等 display class 不再优先于元素上的 hidden 属性。如果希望元素对用户可见,请移除 hidden 属性。注意这不适用于 hidden="until-found"

使用前缀

前缀现在看起来像变体,并且始终位于 class 名的开头:

html
<!-- [!code classes:tw:bg-red-500,tw:flex,tw:hover:bg-red-600] -->
<div class="tw:flex tw:bg-red-500 tw:hover:bg-red-600">
  <!-- ... -->
</div>

使用前缀时,主题变量仍应按「未使用前缀」的方式配置:

css
@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 变量带上前缀,以免与项目中已有变量冲突:

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);

  /* ... */
}

important 修饰符

在 v3 中,可以在 utility 名开头(但在所有变体之后)放一个 ! 来标记为 important。在 v4 中,应把 ! 放在 class 名的最末尾:

html
<!-- [!code classes:bg-red-500!,flex!,hover:bg-red-600/50!] -->
<div class="flex! bg-red-500! hover:bg-red-600/50!">
  <!-- ... -->
</div>

旧写法仍为兼容而支持,但已弃用。

添加自定义 utility

在 v3 中,你在 @layer utilities@layer components 中定义的自定义 class 会被 Tailwind 识别为真正的 utility class,并自动与 hoverfocuslg 等变体一起工作;区别在于 @layer components 在生成的样式表中始终排在前面。

在 v4 中我们使用原生层叠层,不再劫持 @layer at-rule,因此引入了 @utility API 作为替代:

CSS
css
@layer utilities {
  .tab-4 {
    tab-size: 4;
  }
}
@utility tab-4 {
  tab-size: 4;
}

自定义 utility 现在还会按所定义属性的数量排序。这意味着像 .btn 这样的组件 utility 可以被其他 Tailwind utility 覆盖,无需额外配置:

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

关于注册自定义 utility 的更多信息,见添加自定义 utility 文档

变体叠加顺序

在 v3 中,叠加的变体从右到左应用;v4 中改为从左到右,更接近 CSS 语法。

要适配此变更,请把项目中任何对顺序敏感的叠加变体顺序反过来:

HTML
html
<!-- prettier-ignore -->
<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>

这类写法即使有也通常很少——最可能用到的是直接子元素变体(*)以及 typography 插件的变体(prose-headings),而且也只有在它们与其他变体叠加时才需要关心。

任意值中的变量

在 v3 中,可以把 CSS 变量当作任意值使用而无需 var();但 CSS 的近期更新使这种写法常常产生歧义,因此 v4 把语法改成使用圆括号而不是方括号。

要适配此变更,请把旧的变量简写语法替换为新的变量简写语法:

HTML
html
<div class="bg-[--brand-color]"></div>
<div class="bg-(--brand-color)"></div>

grid 与 object-position utility 中的任意值

此前,grid-cols-*grid-rows-*object-* utility 的任意值中,逗号会被替换为空格。这种特殊行为存在于 Tailwind CSS v3,是为了兼容 v2。v4.0 不再提供该兼容,必须用下划线表示空格。

要适配此变更,请把本意表示空格的逗号替换为下划线:

HTML
html
<div class="grid-cols-[max-content,auto]"></div>
<div class="grid-cols-[max-content_auto]"></div>

移动端的 hover 样式

在 v4 中,我们更新了 hover 变体,仅在主输入设备支持悬停时才应用:

CSS
css
@media (hover: hover) {
  .hover\:underline:hover {
    text-decoration: underline;
  }
}

如果你的站点依赖触摸设备点按时触发 hover,这可能会带来问题。若这是你的情况,可以用采用旧实现的自定义变体覆盖 hover 变体:

CSS
css
@custom-variant hover (&:hover);

不过通常我们建议把 hover 功能当作增强,而不是让站点依赖它才能工作,因为触摸设备并没有真正的悬停能力。

过渡 outline-color

transitiontransition-colors utility 现在包含 outline-color 属性。

这意味着,如果你在 focus 时添加带自定义颜色的轮廓,会看到颜色从默认色过渡过来。为避免这种情况,请无条件设置轮廓颜色,或在两个状态都显式设置:

HTML
html
<button class="transition hover:outline-2 hover:outline-cyan-500"></button>
<button class="outline-cyan-500 transition hover:outline-2"></button>

独立的 transform 属性

rotate-*scale-*translate-* utility 现在基于 CSS 中各自独立的 rotatescaletranslate 属性。通常这不应影响行为,但有几种情况需要注意:

重置 Transform

以前可以通过 transform-none「重置」rotate、scale、translate utility。现在不再有效,需要分别重置各个属性:

HTML
html
<button class="scale-150 focus:transform-none"></button>
<button class="scale-150 focus:scale-none"></button>

过渡

如果自定义过渡属性列表并包含 transform(例如写成 transition-[opacity,transform]),这些 utility 将不再产生过渡。修复方法是在列表中包含各个独立属性。例如,若希望在使用 opacity-*scale-* utility 时过渡变化,应改用 transition-[opacity,scale]

HTML
html
<button class="transition-[opacity,transform] hover:scale-150"></button>
<button class="transition-[opacity,scale] hover:scale-150"></button>

禁用核心插件

在 v3 中有一个 corePlugins 选项,可以彻底禁用框架中的某些 utility。v4 不再支持该选项。

使用 theme() 函数

由于 v4 会为所有主题值提供 CSS 变量,我们建议尽可能使用这些变量,而不是 theme() 函数:

CSS
css
.my-class {
  background-color: theme(colors.red.500);
  background-color: var(--color-red-500);
}

如果仍需使用 theme() 函数(例如在不支持 CSS 变量的媒体查询中),应使用 CSS 变量名,而不是旧的点记法:

CSS
css
@media (width >= theme(screens.xl)) { 
@media (width >= theme(--breakpoint-xl)) { 
  /* ... */
}

使用 JavaScript 配置文件

JavaScript 配置文件仍为向后兼容而支持,但在 v4 中不再自动检测。

如果仍需使用 JavaScript 配置文件,可以用 @config 指令显式加载:

CSS
css
@config "../../tailwind.config.js";

基于 JavaScript 的配置中的 corePluginssafelistseparator 选项在 v4.0 中不受支持。要在 v4 中把 utility 加入 safelist,请使用 @source inline()

在 JavaScript 中使用主题值

在 v3 中我们导出了 resolveConfig 函数,可以把基于 JavaScript 的配置转换成扁平对象,供其他 JavaScript 使用。

我们在 v4 中移除了它,希望大家直接使用我们生成的 CSS 变量——这样更简单,也能显著减小打包体积。

例如,流行的 React 库 Motion 支持从 CSS 变量值做动画:

JSX
jsx
// [!code word:var(--color-blue-500)]
<motion.div animate={{ backgroundColor: "var(--color-blue-500)" }} />

如果需要在 JS 中访问已解析的 CSS 变量值,可以使用 getComputedStyle 获取文档根元素上的主题变量值:

spaghetti.js
js
let styles = getComputedStyle(document.documentElement);
let shadow = styles.getPropertyValue("--shadow-xl");

在 Vue、Svelte 或 CSS modules 中使用 @apply

在 v4 中,与主 CSS 文件分开打包的样式表(例如 CSS modules 文件,以及 Vue、Svelte、Astro 中的 <style> 块等)无法访问其他文件中定义的主题变量、自定义 utility 和自定义变体。

要在这些上下文中使用这些定义,请用 @reference 导入它们,而不会在打包结果中重复 CSS:

Vue
html
<template>
  <h1>Hello world!</h1>
</template>

<style>
  @reference "../../app.css";

  h1 {
    @apply text-2xl font-bold text-red-500;
  }
</style>

或者,也可以完全不用 @apply,直接使用 CSS 主题变量;这还能提升性能,因为 Tailwind 不必处理这些样式:

Vue
html
<template>
  <h1>Hello world!</h1>
</template>

<style>
  h1 {
    color: var(--text-red-500);
  }
</style>

使用 Sass、Less 和 Stylus

Tailwind CSS v4.0 并不设计为与 Sass、Less 或 Stylus 等 CSS 预处理器一起使用。把 Tailwind CSS 本身当作预处理器——你不应该把 Tailwind 和 Sass 一起用,就像你不会把 Sass 和 Stylus 一起用一样。因此,无法在样式表或 Vue、Svelte、Astro 等的 <style> 块中使用 Sass、Less 或 Stylus。

更多信息见兼容性文档

文档译文以 MIT 协议授权;原文版权归 Tailwind Labs。湘ICP备2026005453号-2