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 的动态能力可能更合适

相关推荐
小彭努力中4 小时前
194.Vue3 + OpenLayers 实战:动态位置 + 高度 + 角度,模拟卫星地面覆盖范围
前端·css·vue.js·openlayers·animate
Luna-player10 小时前
Vue 组件,用来实现一个响应式图标网格布局,核心是用 CSS 实现固定宽高比的正方形容器,并在里面放置图片和文字。
前端·css·vue.js
Greg_Zhong12 小时前
Css知识之伪类和伪元素
前端·css
余瑜鱼鱼鱼13 小时前
css常用功能总结(三)(Chrome 调试工具 -- 查看 CSS 属性)
前端·css·chrome
Dxy123931021613 小时前
HTML常用CSS样式推荐:打造高效、美观的网页设计
前端·css·html
Predestination王瀞潞13 小时前
6.5.1 软件->W3C HTML5、CSS3标准(W3C Recommendation):CSS(Cascading Style Sheet)
css·css3·html5
xiaotao1311 天前
什么是 Tailwind CSS
前端·css·css3
xiaotao1311 天前
03. 原子化 CSS 思想
前端·css·tailwind
爱宇阳1 天前
Nuxt4 + Tailwind CSS v4 自定义响应式断点完整指南
前端·css·nuxt4
孟祥_成都1 天前
前端下午茶:这 3 个网页特效建议收藏(送源码)
前端·javascript·css