CSS 编写与管理范式 - Tailwind和CSS-in-JS

Tailwind CSSCSS-in-JS 是两种完全不同的 CSS 编写与管理范式,代表了现代前端在"如何高效、可维护地处理样式"上的两种主流思路。

下面从本质、原理、使用方式到优劣对比,为你系统梳理:


一、Tailwind CSS:原子化(Utility-First)CSS 框架

✅ 是什么?

  • 一个 预定义大量原子化工具类(Utility Classes) 的 CSS 框架。
  • 直接在 HTML/JSX 中组合这些类名 来构建 UI,不写传统 CSS
  • 样式最终通过 @tailwind base; @tailwind components; @tailwind utilities; 引入,并在构建时自动剔除未使用的类(JIT 模式)。

示例

jsx 复制代码
// 用 Tailwind 写一个按钮
<button className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 transition">
  Click me
</button>

每个 class 对应一个 CSS 属性:bg-blue-500background-color: #3b82f6;

核心特点

  • 实用优先(Utility-First):不提供"按钮组件",只提供"积木块"。
  • 设计系统约束 :颜色、间距、断点等由 tailwind.config.js 统一配置,保证一致性。
  • 响应式 & 状态变体简单md:text-centerhover:bg-red-500dark:bg-gray-800
  • 生产 CSS 极小:仅包含项目中实际用到的类。
  • 需配合构建工具 (Vite/Webpack) + Tailwind 配置文件

💡 有趣的是:shadcn/ui 虽然基于 Tailwind,但其组件内部其实用了 radix UI(无样式)+ Tailwind(样式),本质上是一种"Tailwind 版的组件封装",兼顾了两者的优点。


二、CSS-in-JS:将 CSS 写在 JavaScript 中

✅ 是什么?

  • 一种 在 JS/TS 文件中直接定义样式 的技术方案。
  • 样式以 JavaScript 对象或模板字符串 形式存在,运行时动态生成 <style> 标签注入 DOM。
  • 主流库:styled-componentsEmotionStitches 等。

示例(以 styled-components 为例)

jsx 复制代码
import styled from 'styled-components';

const Button = styled.button`
  background: ${props => props.primary ? '#007bff' : '#e9ecef'};
  color: white;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  &:hover {
    opacity: 0.9;
  }
`;

function App() {
  return <Button primary>Click me</Button>;
}

核心特点

  • 组件级作用域 :自动生成唯一 class 名(如 sc-bdVaMY),避免全局污染。
    CSS-in-JS 库在 运行时对样式内容进行处理,生成一个几乎不可能重复的字符串作为 class 名,有多种生成策略,比如基于样式内容的哈希,基于组件名+计数器等等。
  • 动态样式:直接使用 JS 变量、props、state 控制样式。
  • 逻辑与样式同文件:符合 React 组件化思想。
  • 运行时注入 :样式在 JS 执行时生成并插入 <head>
  • 无需额外 CSS 文件 :一切在 .js/.tsx 中完成。

三、核心区别对比表

维度 Tailwind CSS CSS-in-JS
编写位置 HTML/JSX 的 className 属性中 JavaScript/TypeScript 文件内部
样式形式 预定义的 CSS 类名(字符串) JS 对象 / 模板字符串
作用域 全局类名(但通过命名约定避免冲突) 自动局部作用域(唯一 class 名)
动态能力 有限(需结合 JS 条件拼接 class) 原生支持(直接用 props/state)
构建时 vs 运行时 构建时生成静态 CSS(无运行时开销) 运行时生成 CSS(有轻微性能成本)
包体积影响 最终 CSS 小;无 JS 运行时 增加 JS bundle(如 styled-components ~10KB)
主题切换 通过 CSS 变量 + dark: 前缀 通过 ThemeProvider + props
调试体验 浏览器 DevTools 显示清晰类名(如 bg-blue-500 显示随机 class 名(如 sc-123abc),需插件辅助
学习曲线 需记忆大量工具类(但文档完善) 需理解 JS 作用域和模板字符串
典型用户 Vercel (Next.js)、Shopify、Netflix Atlassian、Airbnb、早期 GitHub

四、如何选择?

✅ 选 Tailwind CSS 如果:

  • 你追求 极致性能(无运行时、纯静态 CSS)
  • 你希望 快速搭建一致 UI(受设计系统约束)
  • 你习惯 声明式、组合式 的开发方式
  • 你使用 Next.js、Remix 等 SSR 框架(Tailwind 与之深度集成)

✅ 选 CSS-in-JS 如果:

  • 你需要 高度动态的样式(如根据 API 数据变色)
  • 你坚持 样式与组件完全封装(真正"组件即一切")
  • 你讨厌 全局 CSS 命名冲突 的历史包袱
  • 你的团队已熟悉 styled-components 生态

五、趋势与融合

  • Tailwind 正在吸收 CSS-in-JS 优点

    • 支持 @apply 封装组件类
    • 支持任意值 text-[#123456]
    • 结合 clsx/cva 实现条件 class 组合
  • CSS-in-JS 也在优化性能

    • Emotion 支持 css prop + Babel 插件提取关键 CSS
    • Linaria、Astro 等实现 编译时 CSS-in-JS(零运行时)

💡 有趣的是:shadcn/ui 虽然基于 Tailwind,但其组件内部其实用了 radix UI(无样式)+ Tailwind(样式),本质上是一种"Tailwind 版的组件封装",兼顾了两者的优点。


总结一句话:

Tailwind 是"用类名拼 UI",CSS-in-JS 是"用 JS 写 CSS"。前者重 构建时效率 设计约束**,后者重运行时灵活性组件封装。没有绝对好坏,只有是否匹配你的项目需求与团队习惯。**

如果你刚开始新项目,且用 Next.js + Tailwind,Tailwind 是更安全、高效的选择

如果你在做高度定制化的可视化应用,CSS-in-JS 的动态能力可能更合适

相关推荐
RFCEO1 天前
前端编程 课程十六、:CSS 盒子模型
css·前端基础课程·css盒子模型·css盒子模型的组成·精准控制元素的大小和位置·css布局的基石·内边距(padding)
夏幻灵2 天前
CSS三大特性:层叠、继承与优先级解析
前端·css
会编程的土豆2 天前
新手前端小细节
前端·css·html·项目
珹洺2 天前
Bootstrap-HTML(二)深入探索容器,网格系统和排版
前端·css·bootstrap·html·dubbo
BillKu2 天前
VS Code HTML CSS Support 插件详解
前端·css·html
1024小神3 天前
用css的clip-path裁剪不规则形状的图片展示
前端·css
GGGG寄了3 天前
CSS——文字控制属性
前端·javascript·css·html
HWL56793 天前
在网页中实现WebM格式视频自动循环播放
前端·css·html·excel·音视频
HWL56793 天前
防止移动设备自动全屏播放视频,让视频在页面内嵌位置正常播放
前端·css·音视频