关于 tailwind-v4
编写符合 Tailwind CSS v4 习惯的实用指南,帮助避免过时的 v3 写法,涵盖 CSS 优先配置、工具类变化、变体和动效,并建议核对锁定版本。
主要功能
- 01CSS 优先配置指南
- 02v3 到 v4 的工具类与语法变化
- 03优先使用生成的工具类而非任意值
- 04以变体替代自定义 CSS 或 JavaScript 的样式方案
- 05v4 行为变化与动效指引
适用场景
- 01编写新的 Tailwind CSS v4 样式
- 02更新使用 v3 旧语法的代码
- 03按项目锁定版本核对工具类
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mastra-ai/ mastra --skill tailwind-v4安装后在 Claude Code 中输入/tailwind-v4确认已加载。
详细介绍
Tailwind CSS v4
如何编写符合习惯的 Tailwind v4 代码,并识别仍能编译但不应出现在新代码中的 v3 时代语法。
版本与来源
在使用较新的工具类之前,请先检查固定版本:playground 包会在其 package.json 中固定 tailwindcss 版本(撰写本文时为 4.3.3,包括 scrollbar-*、zoom-* 和 tab-* 等 v4.3 工具类)。如果不确定某个工具类、变体或指令在固定版本中是否存在,请查阅文档而不要凭猜测:
- 工具类与变体参考:https://tailwindcss.com/docs
- v3 → v4 迁移:https://tailwindcss.com/docs/upgrade-guide
- 各次小版本新增内容:https://tailwindcss.com/blog/tailwindcss-v4(以及
/tailwindcss-v4-1、/tailwindcss-v4-3等)
CSS 优先的配置
Tailwind v4 通过 CSS 进行配置,而不是 JavaScript。
| 推荐用法 | 禁止使用(v3 时代) |
|---|---|
@import 'tailwindcss' | @tailwind base/components/utilities |
对于应生成工具类的令牌,使用 @theme { --color-x: ...; } | 新项目中使用 tailwind.config.ts |
对于自定义工具类,使用 @utility name { ... }(支持变体) | @layer utilities { .name { ... } } |
@custom-variant dark (&:is(.dark *)) | JS plugins / addVariant |
使用 @source "path" / @source inline("...") 添加额外源文件或设置安全列表 | content 数组 / safelist 配置 |
在自定义 CSS 中使用 @variant dark { ... } 应用 Tailwind 变体 | 重复编写媒体查询或选择器 |
在作用域样式(Vue、CSS Modules)中使用 @reference "app.css" 配合 @apply | 重复导入样式表 |
CSS 中使用 var(--color-x),JS 中使用 getComputedStyle | theme() 函数、resolveConfig |
@config "…" / @plugin "…" 仅用于已有的 JS 配置集成 | 添加新的 JS 配置或插件 |
@theme 变量属于 API:每个变量都会输出原生 CSS 变量,并生成工具类(--color-* → bg-*/text-*/border-*/...,--text-* → text-*,--shadow-* → shadow-*,--animate-* → animate-*,--breakpoint-* → 响应式变体)。普通的 :root { --x: ...; } 变量不会生成任何工具类,适用于仅在运行时使用的值。当某个令牌的值引用了另一个变量(--color-x: var(--y))时,应在 @theme inline 中声明,使工具类在声明处解析该引用。在自定义 CSS 中,--alpha(var(--color-x) / 50%) 和 --spacing(4) 可替代 v3 中的 theme() 计算。
v3 → v4 重命名
裸名称在比例尺上整体下移了一级,因此沿用 v3 写法会悄无声息地渲染得更小或更轻:
| v3 | v4 |
|---|---|
shadow-sm / shadow | shadow-xs / shadow-sm |
drop-shadow-sm / drop-shadow | drop-shadow-xs / drop-shadow-sm |
blur-sm / blur | blur-xs / blur-sm |
rounded-sm / rounded | rounded-xs / rounded-sm |
outline-none | outline-hidden(对无障碍友好);outline-none 现在会真正移除轮廓 |
ring(3px) | ring-3;默认 ring 现为 1px currentColor |
bg-opacity-50, text-opacity-* | 透明度修饰符:bg-black/50, text-white/50 |
bg-gradient-to-r | bg-linear-to-r(另有新增的 bg-conic-*、bg-radial-*) |
!bg-red-500(前缀) | bg-red-500!(后缀) |
flex-shrink-* / flex-grow-* | shrink-* / grow-* |
bg-[--var] | bg-(--var);方括号现在需要写成 bg-[var(--var)] |
grid-cols-[a,b](逗号) | 使用下划线:grid-cols-[max-content_auto] |
优先使用生成的工具类,而非任意值
间距比例尺是无限的,任意数字都可通过 calc(var(--spacing) * n) 编译,因此大多数 v3 时代的任意值都有对应的命名形式:
| 不推荐 | 推荐 |
|---|---|
min-w-[400px], w-[600px] | min-w-100, w-150 |
h-[1.5rem] w-[1.5rem] | size-6 |
mt-[68px] | mt-17 |
grid-cols-[repeat(15,minmax(0,1fr))] | grid-cols-15 |
h-[100dvh], w-[100dvw], h-[1lh] | h-dvh, w-dvw, h-lh |
max-w-[80rem] | max-w-7xl(容器比例尺) |
data-[current]:opacity-100 | data-current:opacity-100(取值保留方括号:data-[state=open]:) |
bg-[var(--row-bg)] | bg-(--row-bg);存在歧义时使用类型提示:text-(color:--fg), text-(length:--size) |
对于真正的一次性用法,方括号仍然是正确的:max-h-[calc(100dvh-3rem)]、grid-cols-[200px_minmax(0,1fr)],以及 [mask-type:luminance] 这类任意属性。
类名字符串必须保持完整且可被静态检测:应将 props 映射为完整字符串({ success: 'bg-positive1' }[tone]),切勿拼接类似 `bg-${tone}-500` 的片段。
能用变体实现的,就不要手写 CSS 或 JS
在编写样式表规则、style 属性或用于样式的事件处理器之前,先检查是否有对应的变体:
| 手写方式 | Tailwind |
|---|---|
CSS 中的 .btn:active { ... } | active:bg-surface5 |
:focus-visible 规则 | focus-visible:outline-accent1 |
[aria-expanded="true"] 选择器 | aria-expanded:rotate-180(任意 aria-* 布尔值或取值) |
[data-state="open"] 选择器 | data-[state=open]:opacity-100,布尔形式:data-current: |
| 通过 JS 的 hover/focus 状态来样式化同级或子元素 | group/group-hover:、peer/peer-checked:、in-focus: |
| 父级状态选择器 / JS 的“有子元素”检查 | has-checked:bg-accent1、has-[>svg]:pl-8 |
CSS 中的 mask-image / 渐隐渐变 | mask-b-from-80%、mask-t-from-* |
@media (hover: none) 代码块 | pointer-coarse: / pointer-fine: |
| CSS 中的 first/last/nth 规则 | first:、last:、odd:、nth-3:、not-first: |
| 在 CSS 中统一样式化所有子元素 | *:rounded-full(子元素)、**:data-avatar:rounded-full(后代元素) |
新增能力:优先使用,而非取巧或 JS
field-sizing-content:无需 JS resize 监听即可实现自动增高的 textarea。wrap-anywhere/wrap-break-word:在 flex 中断开长单词,无需min-w-0这类取巧写法。items-center-safe、justify-center-safe:溢出时回退为start的居中方式。pointer-coarse:/pointer-fine::无需 user-agent 嗅探即可适配触控目标。user-valid:/user-invalid::仅在用户交互后才应用校验样式(不同于:valid)。starting:(配合transition-discrete用于display/popover):无需 JS 挂载技巧即可实现进入过渡。text-shadow-*、mask-t-from-*/mask-b-to-*(渐隐边缘)、scheme-dark(原生控件/滚动条)、3D 变换(rotate-x-*、perspective-*)。
需要留意的行为变化
- 变换使用独立的 CSS 属性:自定义 transition 列表应使用
transition-[opacity,scale],而非transition-[opacity,transform];可用scale-none/rotate-none/translate-none重置。 hover:仅在支持悬停的设备上生效(@media (hover: hover))——切勿把必需的触控功能放在 hover 之后。- 默认的
border-*、divide-*、ring 和 outline 颜色为currentColor——颜色重要时请显式设置。 - 变体叠加从左到右生效:v3 的
first:*:pt-0现在写作*:first:pt-0。 space-x/y-*的选择器已改变(:not(:last-child));优先使用带gap-*的 flex/grid。- 容器查询已内置:在父元素上使用
@container,在子元素上使用@sm:/@max-md:。 - 实用的 v4 变体:
starting:(进入过渡)、not-*、in-*(类似不带group类的group-*)、nth-*、*:(直接子元素)、**:(后代元素)、inert:。
动效
- 为装饰性动画加上条件控制:
motion-safe:animate-spin motion-reduce:animate-none。 - 可复用的动画使用
--animate-*令牌,并将其@keyframes放在@theme中;局部的一次性动画使用animate-(--local-animation)或animate-[...]。