Tailwind CSS 是开历史倒车吗?

大家好,又是我,刘布斯。

上次聊完AI热潮下的建议,有一个读者私信我,能不能聊聊 Tailwind CSS?团队里有人想推,但他觉得这写出来的 HTML 跟“代码乱葬岗”一样,看着就头大,感觉是在开历史的倒车。

你还真别说,他这感觉,我当初也有。

我第一次看到 Tailwind 的代码,第一反应就是:“这不就是把 CSS 属性名换了个写法,然后怼进 class 里吗?跟早年间写 style="..." 有啥本质区别?前端发展了这么多年,好不容易搞出 CSS-in-JS、Scoped CSS 这些方案,实现了结构和样式的分离,怎么又回去了?”

当时我带着这种“审判”的眼光,在团队里是明确投了反对票的。

但大概一年多前,我接手一个内部的管理后台重构项目,周期紧,人力少,设计稿又变得快。我以前那套 BEM 命名法 + Scoped CSS 的工作流,在那个项目里让我痛苦不堪:

  • 心智负担重:每天花在想 class 名字上的时间,比写样式的时间都长。user-profile__avatar--large-highlighted,写出这种名字的时候,我自己都觉得累。
  • 文件反复横跳:改个样式,先在 Vue 文件里找到结构,再切到 <style> 标签,有时候甚至是独立的 .scss 文件。来回切换,思路总被打断。
  • 冗余和不一致:项目大了,总会出现好几个地方都写了 display: flex; align-items: center; justify-content: center;,但散落在不同文件里,很难统一维护。

就在那个节骨眼上,我抱着“死马当活马医”的心态,在一个新页面上试了试 Tailwind。然后…嗯,就“真香”了。

今天我就不站队,不吹也不黑,纯粹从一个一线开发者的角度,聊聊我是怎么理解和使用 Tailwind 的,希望能帮你拨开迷雾,看清它的本质。

心态转变:你不是在“写样式”,而是在“拼组件”

要想入门 Tailwind,第一步不是学它的语法,而是扭转一个观念:放弃“先写 HTML 结构,再为其添加样式”的传统思路。

Tailwind 的核心是 **Utility-First (功能类优先)**。它已经把 CSS 里几乎所有的属性,都给你预设成了一个个语义化的、原子化的 class

比如:

  • padding: 1rem;  ->  p-4
  • display: flex; -> flex
  • align-items: center; -> items-center
  • font-weight: bold; -> font-bold
  • color: red; (某个色号) -> text-red-500

你要做的,不是去想“这个按钮该叫什么 class”,而是“这个按钮长什么样”。

举个例子,做一个按钮:

以前的思路:

  1. HTML: <button class="primary-button">Click Me</button>
  2. CSS:
    .primary-button {
    background-color#3b82f6;
    color: white;
    padding0.5rem1rem;
    border-radius0.25rem;
    font-weight600;
    }
    .primary-button:hover {
    background-color#2563eb;
    }

用 Tailwind 的思路:直接在 HTML 里描述这个按钮的样子:

<button class="bg-blue-500 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded">
  Click Me
</button>

你看,bg-blue-500 (蓝色背景), hover:bg-blue-700 (鼠标悬浮时变深蓝), text-white (白字), py-2 px-4 (纵向和横向的 padding), rounded (圆角)。

写完这一行,这个按钮的样式就彻底闭环了。我不需要再打开任何 CSS 文件,不需要再为它绞尽脑汁想个名字。我的所有注意力,都集中在“实现这个 UI”这件事上。 这种开发体验带来的心流,一旦适应了,真的回不去。

入门三板斧:掌握这几点,你就能上手了

Tailwind 的 class 看着多,但你完全不需要背。它的命名极其规律,加上现在编辑器插件(比如 Tailwind CSS IntelliSense)做得非常牛,基本你打个首字母,提示就全出来了。你真正需要理解的,是它的几个核心思想:

  1. 响应式设计:这是 Tailwind 的一大杀器。想让一个元素在小屏幕上是 block,在中等屏幕(md)及以上变成 flex

    <div class="block md:flex">...</div>

    就这么简单!一个 md: 前缀就搞定了。再也不用去 CSS 文件里写一堆 @media (min-width: 768px) { ... } 了。

  2. 状态修饰hoverfocusdisabled 等伪类,加个前缀。

    <input class="border-gray-300 focus:border-blue-500 focus:outline-none ...">

    输入框默认是灰色边框,聚焦时变成蓝色边框,并且去掉默认的 outline。语义清晰,一目了然。

  3. @apply:解决“代码乱葬岗”的终极武器

    这就要说到大家最诟病的“class 太长”的问题了。如果一个按钮样式在项目里到处都要用,难道我每次都要复制粘贴那一长串 class 吗?

    当然不是。Tailwind 提供了 @apply 指令,让你可以在 CSS 文件里,把一堆功能类组合成一个自定义的 class。

    比如,在你的 input.css 文件里:

    @tailwind base;
    @tailwind components;
    @tailwind utilities;

    @layer components {
      .btn-primary {
        @apply bg-blue-500 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded;
      }
    }

    然后,在你的 HTML 里,就可以像以前一样,清爽地写:

    <button class="btn-primary">Click Me</button>

    你看,这不就把“开发的爽”和“维护的爽”结合起来了吗?

    对于需要大量复用的、确定性的组件,用 @apply 封装一下,是最佳实践。而对于那些一次性的、布局类的样式,直接用功能类怼上去,效率最高。

一些小小的踩坑经验

  • 别被默认值框死了:Tailwind 的颜色、间距等都是预设的,但这些都可以在 tailwind.config.js 文件里轻松扩展。你们公司的 UI 设计规范里的主色调、字号、间距,都应该先在这里配置好。这样,团队所有人用的都是 bg-primarytext-lg,而不是某个具体的 hex 色值或 px 值,维护性和一致性瞬间拉满。

  • 组件化思维是解药:如果你用的是 React 或 Vue,那些看起来很长的 class 根本不是问题。因为你很快就会把那个按钮封装成一个 <Button> 组件。那串长长的 class 只会存在于 Button.vue 这一个文件里。在其他地方,你用的都是 <Button primary>Click Me</Button>。所以,Tailwind 和组件化开发是天作之合,它会“逼着”你去做更好的组件抽象。

  • 小心和老项目的 CSS 冲突:在一个已经有大量全局 CSS 的老项目里引入 Tailwind,可能会遇到样式覆盖和权重问题。这时候要格外小心,可以考虑开启 Tailwind 的 preflight (一个基础样式重置) 或者有选择性地使用它。最好的场景还是在新项目里从零开始用。

说到底,Tailwind CSS 不是银弹,它是一种更偏向“工程化”的 CSS 解决方案。它牺牲了一点点 HTML 的“纯净度”,换来的是极高的开发效率、强大的可维护性和几乎不会增长的 CSS 文件体积

对于大部分以组件为基础的现代前端应用,尤其是需要快速迭代的中后台、移动端应用,我个人认为,它是一个非常值得尝试的工具。

但你也别光听我说,也别被网上那些争论吓到。自己动手,用它搭个小页面,比如你的个人博客或者一个to-do list。亲手感受一下那种不用想名字、不用切文件的开发体验,你可能就明白,为什么那么多人对它“黑转粉”了。

最后

还没有使用过我们刷题网站(https://fe.ecool.fun/)或者刷题小程序的同学,如果近期准备或者正在找工作,千万不要错过,题库已经录入 1600 多道前端面试题,除了八股文,还有现在面试官青睐的场景题,甚至最热的AI与前端相关的面试题已经更新,努力做全网最全最新的前端刷题网站。

有会员购买、辅导咨询的小伙伴,可以通过下面的二维码,联系我们的小助手。