背景
在 tailwind v4 中,对于伪元素(::before
、::after
)和状态字段(比如::hover
、:focus
)的顺序约定相比于 v3 而言,是更加符合直觉。
如在 v3 版本中,一个关联伪元素和状态的原子类书写可能是:after:hover:text-white
, 而 v4 中的约定(/建议)顺序变更为: hover:after:text-white
来处理普遍情况。
实质上,这样的顺序也更加契合原生 CSS 的写法。
比如:
a.some-link {
&::after { /.../ }
&:hover::after {
color: white;
}
/* ... */
}
但是随着版本的升级迭代,也带来了更明确的限制,比如在 v3 版本中:我们可能基于 tailwind @apply
关键字在 css 文件中如此书写:
a.some-link {
&::after {
@apply text-red-300 hover:text-white;
}
}
但是这不能在 v4 中如预期地被编译处理。所以当前更推荐的写法是:
a.some-link {
&::after {
@apply text-red-300;
}
&:hover::after {
@apply text-white;
}
}
当然在官方文档(Using @apply with Vue, Svelte, or CSS modules)中,有这样提及:
Alternatively, you can use your CSS theme variables directly instead of using @apply at all, which will also improve performance since Tailwind won't need to process these styles: 或者,您可以直接使用 CSS 主题变量,而不是使用 @apply,这也将提高性能,因为 Tailwind 不需要处理这些样式
即:
a.some-link {
&::after {
color: var(--color-red-300);
}
&:hover::after {
color: var(--color-white);
}
}
但这并不在本文的讨论范围,下面的例子仍然使用 @apply
关键字。
上面的简要提及,也引出了下面正文一节的,提到的一次笔者处理 tailwind 升级到 v4 版本后的一处不易察觉的样式 bug。
正文
在使用 taiwind 官方升级脚本工具:npx @tailwindcss/upgrade
, 尽管处理了项目源码中大多数 tailwind 原子类书写变更。但是比如在 .scss/.css 文件中,一些样式声明中,则不能很好的升级变更,比如以下一段代码(其是处理代码块右上角语言水印戳的样式代码):
pre[data-lang="jsx"] {
&::after {
@apply bg-[#f0db4f] text-black md:bg-transparent md:text-muted-foreground/20;
}
}
以上的一段代码在 v3 版本中,能够如预期的应用样式。但是在 v4 中却失效了,原因可能就是前文提及的对顺序的强约定性,尽管 v3 版本中,关于媒体断点和伪元素的共同出现时顺序和 v4 版本保持了一致性,即: md:before:text-current
, 但是 v4 的编译处理有所变化。
并且就以上面的(本质是当前 v4 版本下错误的/ 非推荐的)代码段的编译结果为例:
(并且经笔者验证,这个编译产物在开发模式和生产模式有明显的差异,所以也就导致了在开发模式下出现非预期的样式声明失效,而生产部署模式下样式又正常如旧的情况)
开发模式下的编译产物
.md-prose-cus pre[data-lang=jsx]:after {
background-color: #f0db4f; // it also works on above md(48rem) breakpoint...
color: var(--color-black);
@media (width >= 48rem) {
background-color: transparent; // BUT NOT WORKING!
}
@media (width >= 48rem) {
color: var(--muted-foreground);
@supports (color: color-mix(in lab, red, red)) {
color: color-mix(in oklab, var(--muted-foreground) 20%, transparent); // BUT NOT WORKING!
}
}
}
生产模式下的编译产物
.md-prose-cus pre[data-lang="jsx"]:after {
color: var(--color-black);
background-color: #f0db4f;
}
@media (min-width: 48rem) {
.md-prose-cus pre[data-lang="jsx"]:after {
color: var(--muted-foreground);
background-color: #0000;
}
@supports (color: color-mix(in lab, red, red)) {
.md-prose-cus pre[data-lang="jsx"]:after {
color: color-mix(in oklab, var(--muted-foreground) 20%, transparent);
} // YEAN, it WORKS
}
}
为何在开发模式下生成 css 样式失效?原因就在于此时“错误的”嵌套层级。
而如果一定需要在单独的 css 文件中结合 @apply
定义样式,那么上面的代码使样式符合预期被应用的写法是:
pre[data-lang="jsx"] {
@apply after:bg-[#f0db4f] after:text-black after:content-[attr(data-lang)] md:after:bg-transparent md:after:text-muted-foreground/20;
}
小结
一个并不算严谨的总结,在我们了解了 tailwind 对部分原子类有约定顺序后,比如:md:hover:before:text-current
, 那么在结合 @apply
书写 css 时,
比如当 css 嵌套层级下的顺序等同于:after:md:[atom-clz]
(即上面的代码例)、after:hover:[atom-clz]
时,并且此时样式的应用不符合预期时,可从这个角度去核验样式的声明是否可以变更,
以让其 css 嵌套层级下的等同顺序:符合官方(多数情况下)建议的:md:after:[atom-clz]
、hover:after:[some-clz]
。
升级 tailwind v4 的一次样式 BUG 修复记录
https://infen.cc/loc-blog/35_tailwind-v4-some-detail-on-pseudo-ele[Copy]转载或引用本文时请遵守“署名-非商业性使用-相同方式共享 4.0 国际”许可协议,注明出处、不得用于商业用途!分发衍生作品时必须采用相同的许可协议。