开源我们对 Tailwind CSS v4.0 的进展
- 日期
- Adam Wathan
去年夏天在 Tailwind Connect 上,我分享了 Oxide 的预览 - 一个我们一直在开发的用于 Tailwind CSS 的全新高性能引擎,旨在简化开发体验并利用近年来 Web 平台的演变。
这个新引擎最初计划作为 v3.x 版本发布,但即使我们致力于向后兼容性,这仍然感觉像是一个新一代的框架,它应该成为 v4.0。
现在还处于早期阶段,我们还有很多工作要做,但今天我们开源了我们的进展,并标记了第一个公开的v4.0.0-alpha,这样你就可以开始尝试它,并帮助我们在今年晚些时候发布稳定版。
为了保留一些稳定版发布的惊喜,我会尽量简短,但如果你喜欢玩非常早期和实验性的东西,这里应该有足够的信息让你开始。
一个为速度而生的新引擎
这个新引擎是一个从头开始的重写,它利用了我们现在对框架的所有了解,更好地模拟了问题空间,使代码更少,速度更快。
- 速度提升高达 10 倍 - 我们可以在 105 毫秒内完成 Tailwind CSS 网站的完整构建,而不是 960 毫秒,或者在 55 毫秒内完成 Catalyst UI 工具包的构建,而不是 341 毫秒。
- 更小的占用空间 - 新引擎的安装尺寸缩小了 35% 以上,即使我们使用了一些更重的原生包,比如我们用 Rust 和 Lightning CSS 重写的部分。
- 在关键位置使用 Rust - 我们将框架中最昂贵和可并行化的部分迁移到了 Rust,同时为了可扩展性,将框架的核心保留在 TypeScript 中。
- 一个依赖项 - 新引擎唯一依赖的是 Lightning CSS。
- 自定义解析器 - 我们编写了自己的 CSS 解析器并设计了适合我们需求的自定义数据结构,这使得我们的解析速度比使用 PostCSS 快两倍以上。
统一的工具链
Tailwind CSS v4 不再只是一个插件 - 它是一个用于处理 CSS 的一体化工具。我们已将 Lightning CSS 直接集成到框架中,因此您无需配置有关 CSS 管道的任何内容。
- 内置
@import
处理 - 无需设置和配置像postcss-import
这样的工具。 - 内置供应商前缀 - 您不再需要将
autoprefixer
添加到您的项目中。 - 内置嵌套支持 - 无需插件即可扁平化嵌套 CSS,它开箱即用。
- 语法转换 - 现代 CSS 功能(如
oklch()
颜色和媒体查询范围)被转换为具有更好浏览器支持的语法。
我们仍在发布 PostCSS 插件,但我们也在探索第一方捆绑器插件,并且我们在这个第一个 alpha 版本中发布了一个官方的 Vite 插件,您可以立即试用。
为现代网络而设计
我们正在展望未来,使用 Tailwind CSS v4 构建一个在未来几年内都感觉尖端的框架。
- 原生级联层 - 我们现在使用真正的
@layer
规则,这解决了我们在过去遇到的许多特异性问题。 - 明确定义的自定义属性 - 我们使用
@property
来定义我们的内部自定义属性,并具有适当的类型和约束,从而可以执行诸如转换背景渐变之类的操作。 - 使用
color-mix
进行透明度修饰 — 使用 CSS 变量定义颜色或调整currentColor
的透明度时,使用我们的透明度修饰语法变得前所未有的简单。 - 核心中的容器查询 — 我们已将对容器查询的支持直接添加到核心,并使用新的
@min-*
和@max-*
变体来支持容器查询范围。
我们还在努力使用广色域颜色刷新我们的调色板,并引入对其他现代 CSS 功能的支持,例如 @starting-style
、锚点定位等等。
可组合变体
新的架构使得可以将作用于其他选择器的变体组合在一起,例如 group-*
、peer-*
、has-*
,以及我们在 v4 中引入的新的 not-*
变体。
在早期版本中,像 group-has-*
这样的变体是在框架中明确定义的,但现在 group-*
可以与现有的 has-*
变体组合,而 has-*
变体可以与其他变体(如 focus
)组合。
<div class="group">
<div class="group-has-[&:focus]:opacity-100">
<div class="group-has-focus:opacity-100">
<!-- ... -->
</div>
</div>
这种可组合性没有限制,你甚至可以编写像 group-not-has-peer-not-data-active:underline
这样的代码,尽管出于某种可怕的原因,你可能需要这样做。
零配置内容检测
你会注意到,至少在这些早期的 alpha 版本中,甚至无法配置你的 content
路径。对于大多数项目来说,你永远不需要再做这件事了——Tailwind 会自动为你找到你的模板文件。
我们使用两种方法之一来实现这一点,具体取决于你将 Tailwind 集成到项目中的方式。
-
使用 PostCSS 插件或 CLI,Tailwind 会扫描您的整个项目以查找模板文件,使用我们内置的一系列启发式方法来保持速度,例如不扫描
.gitignore
文件中的目录,并忽略二进制文件格式。 -
使用 Vite 插件,我们依赖于模块图。这很棒,因为我们确切地知道您实际使用了哪些文件,因此它具有最大的性能,并且没有误报或漏报。我们希望将来在 Vite 生态系统之外,使用其他捆绑器插件扩展这种方法。
我们将来肯定会引入一种方法来明确配置内容路径,但我们很好奇这种自动方法对每个人来说效果如何——它在我们自己的项目中运行得很好。
CSS优先配置
Tailwind CSS v4.0 的主要目标是使框架感觉像原生 CSS,而不是像 JavaScript 库。
安装后,您可以使用常规的 CSS @import
语句将其添加到您的项目中
@import "tailwindcss";
您无需在 JavaScript 配置文件中设置所有自定义项,只需使用 CSS 变量即可
@import "tailwindcss";
@theme {
--font-family-display: "Satoshi", "sans-serif";
--breakpoint-3xl: 1920px;
--color-neon-pink: oklch(71.7% 0.25 360);
--color-neon-lime: oklch(91.5% 0.258 129);
--color-neon-cyan: oklch(91.3% 0.139 195.8);
}
特殊的 @theme
指令告诉 Tailwind 根据这些变量创建新的实用程序和变体,让您在标记中使用诸如 3xl:text-neon-lime
之类的类
<div class="max-w-lg 3xl:max-w-xl">
<h1 class="font-display text-4xl">
Data to <span class="text-neon-cyan">enrich</span> your online business
</h1>
</div>
添加新的 CSS 变量的行为类似于早期版本框架中的 extend
,但您可以通过使用类似 --color-*: initial
的语法清除命名空间来覆盖一组完整的变量,然后再定义所有自定义值
@import "tailwindcss";
@theme {
--color-*: initial;
--color-gray-50: #f8fafc;
--color-gray-100: #f1f5f9;
--color-gray-200: #e2e8f0;
/* ... */
--color-green-800: #3f6212;
--color-green-900: #365314;
--color-green-950: #1a2e05;
}
我们仍在微调一些命名约定,但您可以 在 GitHub 上探索默认主题 以查看哪些内容可供自定义。
如果您不想明确清除默认主题,而是想从头开始,您可以直接导入 "tailwindcss/preflight"
和 "tailwindcss/utilities"
来跳过导入默认主题
@import "tailwindcss";
@import "tailwindcss/preflight" layer(base);
@import "tailwindcss/utilities" layer(utilities);
@theme {
--color-*: initial;
--color-gray-50: #f8fafc;
--color-gray-100: #f1f5f9;
--color-gray-200: #e2e8f0;
/* ... */
--color-green-800: #3f6212;
--color-green-900: #365314;
--color-green-950: #1a2e05;
}
我们还将所有主题值作为原生 CSS 变量提供给您的自定义 CSS 中
:root {
--color-gray-50: #f8fafc;
--color-gray-100: #f1f5f9;
--color-gray-200: #e2e8f0;
/* ... */
--color-green-800: #3f6212;
--color-green-900: #365314;
--color-green-950: #1a2e05;
}
这使得您可以轻松地在任意值中引用任何主题值,而无需使用 theme()
函数
<div class="p-[calc(var(--spacing-6)-1px)]">
<!-- ... -->
</div>
它还使您能够在使用 Framer Motion 等 UI 库时使用主题值,而无需使用 resolveConfig()
函数
import { motion } from "framer-motion"
export const MyComponent = () => (
<motion.div
initial={{ y: 'var(--spacing-8)' }}
animate={{ y: 0 }}
exit={{ y: 'var(--spacing-8)' }}
>
{children}
</motion.div>
)
更新内容
我们不会轻易做出重大更改,但目前在 v4 中有一些值得分享的改变。
- 移除已弃用的实用程序 — 我们移除了很久以前就停止记录的实用程序,例如
text-opacity-*
、flex-grow-*
和decoration-slice
,取而代之的是它们的现代替代品,例如text-{color}/*
、grow-*
和box-decoration-slice
。 - PostCSS 插件和 CLI 是独立的包 — 主
tailwindcss
包不再包含这些,因为并非每个人都需要它们,而是应该使用@tailwindcss/postcss
和@tailwindcss/cli
单独安装。 - 没有默认边框颜色 —
border
实用程序以前默认为gray-200
,但现在它默认为currentColor
,就像浏览器一样。我们做出此更改是为了防止在使用zinc
或slate
或其他颜色作为主要灰色时,意外地将错误的灰色引入项目。 - 环默认情况下为 1px —
ring
实用程序以前默认情况下是 3px 蓝色环,现在它使用currentColor
的 1px 环。我们发现自己在项目中使用ring-*
实用程序作为边框的替代方案,并使用outline-*
用于焦点环,因此我们认为在这里保持一致是一个有益的改变。
还有一些非常底层的实现细节更改,可能会在您的项目中以某种方式出现,但没有像这些更改那样刻意。如果您遇到任何意外情况,请告知我们。
v4.0 路线图
这个新的引擎是一个从头开始的重写,到目前为止,我们一直专注于使用新的配置方法重新构想的开发人员体验。
我们非常重视向后兼容性,这也是我们在今年晚些时候发布稳定版 v4.0 之前需要完成的大部分工作。
- 支持 JavaScript 配置文件 - 重新引入对经典
tailwind.config.js
文件的兼容性,以便轻松迁移到 v4。 - 显式内容路径配置 - 使得能够准确地告诉 Tailwind 您的模板位于何处,即使自动内容检测不适合您的设置。
- 支持其他暗黑模式 - 目前我们只支持使用媒体查询的暗黑模式,还需要重新实现选择器和变体策略。
- 插件和自定义工具 - 我们还没有支持插件,也没有支持编写自动与变体一起使用的自定义工具。显然,我们将在稳定版发布之前实现这些功能。
- 前缀支持 - 目前还没有办法为您的类配置前缀,但我们一定会将其带回来。
- 安全列表和阻止列表 - 目前还无法强制 Tailwind 生成特定类或阻止它生成其他类。
- 支持
important
配置 - 目前还没有办法使所有工具都生成带有!important
的代码,但我们计划实现它。 - 支持
theme()
函数 - 对于新项目来说,这并不需要,因为您现在可以使用var()
,但我们将为了向后兼容性而实现它。 - 独立 CLI - 我们还没有为新引擎开发独立的 CLI,但绝对会在 v4.0 发布之前完成。
除此之外,我相信我们会发现很多需要修复的错误,一些激动人心的新 CSS 功能需要加入,以及一些需要在正式发布之前进行更多完善的新 API。
我不想对具体的发布时间表做出承诺,但我个人希望在夏季假期开始之前将 v4.0 标记为稳定版。
试用 alpha 版本
我们已经发布了几个 alpha 版本,您可以从今天开始在您的项目中使用它。
如果您使用的是 VS Code 的 Tailwind CSS IntelliSense 扩展,请确保从扩展页面切换到预发布版本,如果您使用的是我们的 Prettier 插件,请确保安装最新版本。
如果您发现问题,请在 GitHub 上告知我们。我们真的希望在发布稳定版本之前,这个东西能够万无一失,报告您发现的任何问题将对我们有很大帮助。
使用 Vite
安装 Tailwind CSS v4 alpha 和我们的新 Vite 插件
$ npm install tailwindcss@next @tailwindcss/vite@next
然后将我们的插件添加到您的 vite.config.ts
文件中
import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [tailwindcss()],
})
最后,在您的主 CSS 文件中导入 Tailwind
@import "tailwindcss";
使用 PostCSS
安装 Tailwind CSS v4 alpha 和单独的 PostCSS 插件包
$ npm install tailwindcss@next @tailwindcss/postcss@next
然后将我们的插件添加到您的 postcss.config.js
文件中
module.exports = {
plugins: {
'@tailwindcss/postcss': {}
}
}
最后,在您的主 CSS 文件中导入 Tailwind
@import "tailwindcss";
使用 CLI
安装 Tailwind CSS v4 alpha 和单独的 CLI 包
$ npm install tailwindcss@next @tailwindcss/cli@next
接下来,在您的主 CSS 文件中导入 Tailwind
@import "tailwindcss";
最后,使用 CLI 工具编译您的 CSS
$ npx @tailwindcss/cli@next -i app.css -o dist/app.css