顺风并非答案
花粉
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
过去几年,Tailwind CSS以迅雷不及掩耳之势席卷了前端开发领域。作为一个实用性优先的 CSS 类库,它承诺提供一种全新的样式编写方式,这种方式比直接编写 CSS 更一致、更易维护、速度更快。而且在大多数情况下,它确实兑现了这一承诺。
使用 Tailwind,几乎可以确保项目中使用的所有值都来自同一个数据源。从字体、间距到颜色,所有内容都定义在一个地方。这意味着您的代码能够保持一致,无需临时修改。
这是 Tailwind 的最大理念,也是实用主义优先 CSS 概念的最大优势:组合而不是创建。
Tailwind 通过一个庞大的 CSS 类库来实现这一点,它可以为所有元素设置样式。其理念是,你不再需要编写任何 CSS 代码,而是像搭乐高积木一样,为每个属性组合预定义的类。
对于不熟悉这种工作方式的开发者来说,仅仅看到示例代码就常常会产生本能的反应。
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Button
</button>
不可否认,Tailwind 丑陋不堪。它的开发者在项目主页上也承认了这一点。但这只是吹毛求疵,如果 Tailwind 的做事方式真的能解决我们所有的问题,那么这点代价也微不足道。
问题
这种方法的弊端不在于它丑陋、臃肿(Tailwind会清除未使用的类),也不在于“你还不如直接写内联样式”(你不应该这样做)。问题在于,为了使用类应用一致的值,你还必须为CSS 中所有可能的规则值对创建类,即使这样做没有任何意义。所以最终你会使用类似 `class="text/html"` 这样的类,而不是写成 `class="text/html"`,以及类似 `class="text/html"` 这样的类,而不是写成`class="text/ .blockhtml" display: block` 。.text-centertext-align: center
当然,你可以将 Tailwind 中更实用的类与常规 CSS 混合使用。但这样就破坏了 Tailwind 基于类的样式抽象,而且你必须为每个元素维护两个独立的样式入口点。
“那又怎样?”你可能会问,直接用类名而不是CSS有什么问题?当然,这样确实能节省一些击键次数。但Tailwind在这里却引入了它原本不应该解决的新问题。
重塑 CSS
Tailwind 需要重写所有常规 CSS 的功能,包括媒体查询、伪元素、选择器和状态。所有这些都必须适应纯类的架构。
Tailwind 通过所谓的修饰符来实现这一点。在 Tailwind 类名前加上 `--`,md:它们将仅在md断点以上生效。在末尾加上 `--`,hover:类名将应用于特定:hover状态。以此类推。
这些工具都只是对它们需要弥补的功能缺陷的拙劣模仿。想要选择元素的同级元素?:nth-child还是~得用 CSS。想要定位两个断点之间的设备?还是得用 CSS。想要定位某个元素的子元素?还是得用 CSS。你应该明白我的意思了。
当然,你可以用 CSS 来实现这些功能。虽然被戏称为“备用 CSS”,但几乎每个项目在 Tailwind 的类和修饰符无法满足需求时,都需要一些自定义 CSS。然而,这样做又破坏了 Tailwind 的抽象层,并会给自己带来维护上的麻烦。
既然这一点已成定局,那么为什么还要使用毫无意义的类呢?除了节省几个击键次数之外,这些类并没有比直接block用 CSS 编写代码增加任何一致性或可维护性方面的优势。因为虽然这类填补空白的类本身并没有什么价值,但它们却在我们已经熟知的 CSS 之上,增加了一门新的领域特定语言 (DSL) 需要学习。display: block
经典汤
Tailwind 的每个批评者首先都会抨击它庞大的类字符串。没错,它们确实很丑陋,但谁会在意呢?问题并非出在开发者的表面完美主义上,而是归根结底还是修饰符的问题。
每个应用于修改状态的规则都需要一个带有修饰符的专属类。与 CSS 中状态和伪元素自然而然地组织成逻辑块不同,Tailwind 的修改类很快就会变得庞大而难以维护,必须逐行仔细梳理。
以本文开头提到的按钮为例,我们人为地给它添加了一个::before伪元素图标,但对类的排序却不够重视。
<button class="relative before:absolute bg-blue-500 hover:bg-blue-700 text-white before:left-2 font-bold before:text-sm py-2 px-6 rounded before:top-1/2 before:content-['\f00c'] before:-translate-y-1/2">
Button with icon
</button>
当然,在这个例子中,图标最好作为按钮内部的一个独立元素,但重点依然成立。如果没有(或者即使有)仔细地对类进行排序,这些杂乱无章的代码很快就会变成维护的噩梦。
即时生产能派上用场吗?
Tailwind 的全新即时模式会即时编译你正在使用的类,而不是事后精简庞大的样式表。它允许你直接在任何地方使用修饰符,最重要的是,可以直接在 Tailwind 类中写入任意值,例如margin-[100px]。
这是 Tailwind 的基于类的样式 DSL 中新增的另一项语言特性,旨在修复其自身引入的问题。虽然任意值意味着您不必频繁地跳出 Tailwind 的框架,但也削弱了 Tailwind 的核心价值——为整个项目提供单一数据源。从逻辑上讲,Tailwind JIT 实际上就是在一点一点地重新发明 CSS。
解决方案
正如我一开始所说,Tailwind 的核心理念非常好——一个底层、实用性驱动的设计系统,旨在消除“魔法数字”,并使你的 CSS 代码保持一致。问题出在实现上。
值得庆幸的是,CSS 现在和其他语言一样,也采用了相同的方法来确保值的一致性:变量。CSS 变量,或者更准确地说是CSS 自定义属性,对于这门语言来说还比较新,但已经被所有主流浏览器所采用,并且在 Tailwind 的内部实现中也得到了广泛应用。
例如,Tailwind 的.p-4padding 工具可以这样重写:
:root {
--p-4: 16px;
}
.button {
padding: var(--p-4);
}
由于我们不再需要为每个规则值对编写单独的类,因此可以极大地简化我们以实用性为先的设计系统。我们可以使用一组尺寸变量,将其应用于内边距、外边距、宽度、高度、位置等的任何部分,而无需为每个属性的每种组合编写单独的实用程序。
:root {
--size-2: 8px;
--size-4: 16px;
}
.button {
padding: var(--size-2) var(--size-4);
margin: var(--size-4) 0;
}
由于变量是平台的一部分,它们拥有原生运行时环境。我们可以使用 JavaScript 与 CSS 变量交互,并动态更新它们。这使得诸如为深色模式重新设计整个界面之类的操作成为可能,只需几行代码即可完成,而无需引入任何新的实用程序或工具。
function enableDarkMode() {
document.documentElement.style.setProperty(`--color-background`, `black`);
document.documentElement.style.setProperty(`--color-text`, `white`);
}
那么,与其彻底重新发明样式范式,为什么不将界面中的所有值抽象成一个单一的真理来源,将它们放入可以在任何地方使用的 CSS 变量中,就像使用普通的 CSS 一样,而不会出现所有这些新问题呢?
以身作则
花粉
CSS变量构建系统

Pollen 是一个高度可配置的 CSS 变量库,适用于您的下一代设计系统。它能让您编写出更快、更一致、更易于维护的样式。
由Bokeh的优秀团队用心制作和维护 ❤️ 。
特征
- 功能强大的、经过精心设计且与样式无关的 CSS 变量库
- 完全可配置,并可通过 CLI 构建工具进行扩展
- 无需任何设置即可开始使用
- 响应式设计,支持配置
@media和@supports查询
- 如果您想摆脱 Pollen,它能提供轻量级、易于阅读的输出格式。
它看起来像什么
Pollen 的设计令牌可用于构建任何项目。它们易于定制和扩展,无需预处理器、类命名约定或非标准语法。只需一个简单的配置文件,即可生成完全自定义的设计系统。

工作原理
1. 配置您的设计系统
pollen.config.js
module.exports = (pollen) => ({
output: "./pollen.css",
modules…
Pollen是一个遵循标准的 CSS 库,正是基于这种理念而诞生的。它汲取了 Tailwind 的核心思想,并将其重新实现为一个仅 0.85kb 的纯 CSS 变量集合。得益于 Web 平台现有的工具,它无需重新发明 CSS 的编写方式,即可提供 Tailwind 的所有关键优势。由于它只是纯 CSS,因此可以在任何上下文中以任何方式使用。
但你可能不需要它
坦白说,《花粉》这本书是我写的。但我并不是想推销你采用它,而是想让你了解它背后的理念,并将其运用到你自己的工作中。
Pollen 只是从 Tailwind 转换过来的一些 CSS 变量,希望它们能派上用场。但如果你已经拥有一个完善的设计系统,包含尺寸、字体、颜色以及其他界面共享值,那么你可能不需要 Pollen,当然也不需要 Tailwind。把它们集中写成 CSS 变量,然后在所有地方使用它们。这才是摆脱这种混乱局面的正确方法。
通过使用变量来消除“魔法数字”,从而为 CSS 带来一致性。Tailwind 和 CSS 变量都无法解决 CSS 的其他问题(例如深度组合、继承泄漏和性能优化)。但 Tailwind 引入的新 DSL 反而使这些问题更加棘手。至少,坚持使用常规 CSS,您可以毫无顾虑地使用我们社区过去十年来开发的所有其他模式和工具。
文章来源:https://dev.to/madeleineostoja/tailwind-isnt-the-answer-2opj