Tailwind CSS 实用优先思想 #
什么是实用优先 #
实用优先(Utility-First)是一种 CSS 架构方法,它主张使用小型的、单一用途的类来构建界面,而不是为每个组件编写自定义 CSS。
传统方式 vs 实用优先 #
html
<!-- 传统方式:语义化类名 + 自定义 CSS -->
<style>
.card {
background-color: white;
border-radius: 0.5rem;
padding: 1.5rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.card-title {
font-size: 1.25rem;
font-weight: 600;
color: #111827;
margin-bottom: 0.5rem;
}
.card-description {
color: #6b7280;
line-height: 1.5;
}
.card-button {
margin-top: 1rem;
background-color: #3b82f6;
color: white;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
transition: background-color 0.2s;
}
.card-button:hover {
background-color: #2563eb;
}
</style>
<div class="card">
<h3 class="card-title">标题</h3>
<p class="card-description">描述内容</p>
<button class="card-button">操作</button>
</div>
html
<!-- 实用优先:直接使用实用类 -->
<div class="bg-white rounded-lg p-6 shadow-md">
<h3 class="text-xl font-semibold text-gray-900 mb-2">标题</h3>
<p class="text-gray-500 leading-relaxed">描述内容</p>
<button class="mt-4 bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600 transition-colors">
操作
</button>
</div>
实用优先的优势 #
1. 无需命名 #
传统 CSS 开发中最头疼的问题之一就是命名:
css
/* 到底用哪个名字? */
.card { }
.card-wrapper { }
.card-container { }
.card-box { }
.card-component { }
实用优先完全避免了这个问题:
html
<!-- 直接描述样式,无需命名 -->
<div class="bg-white rounded-lg p-6">
...
</div>
2. 无需切换文件 #
html
<!-- 传统方式:需要在 HTML 和 CSS 之间切换 -->
<!-- HTML -->
<div class="card">...</div>
/* CSS */
.card { ... }
html
<!-- 实用优先:所有样式都在 HTML 中 -->
<div class="bg-white rounded-lg p-6">...</div>
3. 样式局部化 #
html
<!-- 传统方式:CSS 是全局的,可能产生冲突 -->
<style>
.btn { padding: 10px; } /* 全局样式 */
.header .btn { padding: 5px; } /* 需要覆盖 */
</style>
html
<!-- 实用优先:样式直接在元素上,不会冲突 -->
<button class="px-4 py-2">普通按钮</button>
<button class="px-2 py-1">小按钮</button>
4. 更容易维护 #
html
<!-- 传统方式:需要查找 CSS 文件 -->
<div class="card"> <!-- 样式在哪? -->
...
</div>
html
<!-- 实用优先:样式一目了然 -->
<div class="bg-white rounded-lg p-6 shadow-md"> <!-- 样式清晰可见 -->
...
</div>
5. 更小的 CSS 文件 #
css
/* 传统方式:大量重复的 CSS */
.card-1 { background: white; padding: 1rem; border-radius: 0.5rem; }
.card-2 { background: white; padding: 1rem; border-radius: 0.5rem; }
.card-3 { background: white; padding: 1rem; border-radius: 0.5rem; }
/* ...更多重复 */
html
<!-- 实用优先:复用相同的类 -->
<div class="bg-white p-4 rounded-lg">卡片 1</div>
<div class="bg-white p-4 rounded-lg">卡片 2</div>
<div class="bg-white p-4 rounded-lg">卡片 3</div>
常见误解 #
误解 1:内联样式一样? #
html
<!-- 内联样式:无法使用响应式、状态等 -->
<div style="background: blue; padding: 16px;">
内容
</div>
<!-- Tailwind CSS:支持响应式、状态等 -->
<div class="bg-blue-500 p-4 hover:bg-blue-600 md:p-6">
内容
</div>
误解 2:HTML 会变得臃肿? #
html
<!-- 实际上,语义化类名也需要写很多 CSS -->
<div class="card card--featured card--large">
...
</div>
<style>
.card { /* 很多 CSS */ }
.card--featured { /* 很多 CSS */ }
.card--large { /* 很多 CSS */ }
</style>
误解 3:无法复用? #
html
<!-- 使用组件抽象复用 -->
<!-- Button.vue -->
<template>
<button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
<slot />
</button>
</template>
<!-- 使用 -->
<Button>点击我</Button>
何时提取组件 #
规则:重复三次以上 #
html
<!-- 第一次出现 -->
<button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
按钮
</button>
<!-- 第二次出现 -->
<button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
按钮
</button>
<!-- 第三次出现:考虑提取组件 -->
<Button>按钮</Button>
使用 @apply 提取 #
css
/* 不推荐:回到传统 CSS 的老路 */
.btn {
@apply px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600;
}
html
<!-- 推荐:使用组件 -->
<!-- Button.vue -->
<template>
<button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
<slot />
</button>
</template>
组件化示例 #
jsx
// React 组件
function Button({ children, variant = 'primary' }) {
const variants = {
primary: 'bg-blue-500 hover:bg-blue-600 text-white',
secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-800',
danger: 'bg-red-500 hover:bg-red-600 text-white',
}
return (
<button className={`px-4 py-2 rounded ${variants[variant]}`}>
{children}
</button>
)
}
// 使用
<Button>主要按钮</Button>
<Button variant="secondary">次要按钮</Button>
<Button variant="danger">危险按钮</Button>
vue
<!-- Vue 组件 -->
<template>
<button :class="buttonClasses">
<slot />
</button>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
variant: {
type: String,
default: 'primary'
}
})
const variants = {
primary: 'bg-blue-500 hover:bg-blue-600 text-white',
secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-800',
danger: 'bg-red-500 hover:bg-red-600 text-white',
}
const buttonClasses = computed(() =>
`px-4 py-2 rounded ${variants[props.variant]}`
)
</script>
设计约束 #
Tailwind CSS 通过设计约束帮助你保持一致性。
间距约束 #
html
<!-- 推荐:使用预定义值 -->
<div class="p-4"> <!-- 16px -->
<div class="p-6"> <!-- 24px -->
<div class="p-8"> <!-- 32px -->
<!-- 避免:随意值 -->
<div class="p-[15px]"> <!-- 打破设计系统 -->
颜色约束 #
html
<!-- 推荐:使用预定义颜色 -->
<div class="bg-blue-500">
<div class="bg-blue-600">
<div class="bg-blue-700">
<!-- 避免:随意颜色 -->
<div class="bg-[#4a90d9]"> <!-- 打破设计系统 -->
字体约束 #
html
<!-- 推荐:使用预定义字体大小 -->
<p class="text-sm"> <!-- 14px -->
<p class="text-base"> <!-- 16px -->
<p class="text-lg"> <!-- 18px -->
<!-- 避免:随意字体大小 -->
<p class="text-[15px]"> <!-- 打破设计系统 -->
实用优先的工作流程 #
1. 从布局开始 #
html
<div class="min-h-screen flex items-center justify-center">
<!-- 页面内容 -->
</div>
2. 添加容器 #
html
<div class="min-h-screen flex items-center justify-center">
<div class="w-full max-w-md">
<!-- 卡片内容 -->
</div>
</div>
3. 构建组件 #
html
<div class="min-h-screen flex items-center justify-center bg-gray-100">
<div class="w-full max-w-md bg-white rounded-lg shadow-lg p-8">
<h2 class="text-2xl font-bold text-gray-900 mb-6">登录</h2>
<!-- 表单内容 -->
</div>
</div>
4. 添加交互 #
html
<div class="min-h-screen flex items-center justify-center bg-gray-100">
<div class="w-full max-w-md bg-white rounded-lg shadow-lg p-8">
<h2 class="text-2xl font-bold text-gray-900 mb-6">登录</h2>
<form class="space-y-4">
<input class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="邮箱">
<input class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="密码">
<button class="w-full bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600 transition-colors">
登录
</button>
</form>
</div>
</div>
最佳实践 #
1. 保持类名有序 #
html
<!-- 推荐顺序:布局 → 尺寸 → 间距 → 视觉 → 状态 -->
<div class="
flex items-center justify-center
w-full h-12
px-4 py-2
bg-blue-500 text-white rounded-lg
hover:bg-blue-600
">
按钮
</div>
2. 使用组件抽象 #
jsx
// 不要重复相同的类名
function Card({ children }) {
return (
<div className="bg-white rounded-lg shadow-md p-6">
{children}
</div>
)
}
3. 合理使用任意值 #
html
<!-- 必要时使用任意值 -->
<div class="w-[calc(100%-2rem)]">
特殊计算宽度
</div>
4. 利用编辑器插件 #
安装 Tailwind CSS IntelliSense 插件,获得:
- 类名自动补全
- 悬停预览 CSS
- 语法高亮
- 错误提示
下一步 #
理解实用优先思想后,开始学习 布局 掌握具体的实用类使用!
最后更新:2026-03-28