| 版本 | 日期 | 描述 | 作者 |
|---|---|---|---|
| 1.0 | 2025-10-15 | 初始Tailwind CSS样式规范 | Winston |
本文档定义了出行服务项目中Tailwind CSS的使用规范和最佳实践,特别针对Taro小程序环境的适配和优化。
{
"tailwindcss": "^4.1.11",
"weapp-tailwindcss": "^4.2.5",
"@tailwindcss/postcss": "^4.1.11",
"autoprefixer": "^10.4.21",
"postcss": "^8.4.38"
}
// tailwind.config.js
const { iconsPlugin, getIconCollections } = require("@egoist/tailwindcss-icons")
module.exports = {
content: [
'./src/**/*.{html,js,ts,jsx,tsx}',
],
theme: {
extend: {
colors: {
// 项目品牌色
primary: {
50: '#f0f9ff',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
},
// 语义化颜色
destructive: {
50: '#fef2f2',
500: '#ef4444',
600: '#dc2626',
},
},
spacing: {
'18': '4.5rem',
'88': '22rem',
},
borderRadius: {
'4xl': '2rem',
}
},
},
plugins: [
iconsPlugin({
collections: getIconCollections(["mdi", "lucide", "heroicons"]),
}),
],
corePlugins: {
preflight: false, // 小程序环境禁用preflight
},
}
// config/index.ts
mini: {
webpackChain(chain) {
chain.merge({
plugin: {
install: {
plugin: UnifiedWebpackPluginV5,
args: [{
cssSelectorReplacement: {
universal: ['view','text','button', 'input']
},
cssChildCombinatorReplaceValue: ['view', 'text', 'button', 'input']
}]
}
}
})
}
}
推荐做法:
// ✅ 使用原子化类名
<View className="flex items-center justify-between p-4 bg-white rounded-lg shadow-sm">
<Text className="text-lg font-semibold text-gray-900">标题</Text>
<Button className="px-3 py-1 bg-blue-500 text-white rounded">按钮</Button>
</View>
不推荐做法:
// ❌ 避免自定义CSS类
<View className="card-container">
<Text className="card-title">标题</Text>
<Button className="card-button">按钮</Button>
</View>
// 对应的CSS
.card-container { /* ... */ }
.card-title { /* ... */ }
.card-button { /* ... */ }
移动端优先:
<View className="w-full md:w-1/2 lg:w-1/3">
<Text className="text-sm md:text-base lg:text-lg">响应式文本</Text>
</View>
小程序专用响应式:
<View className="w-full min-[375px]:w-11/12 min-[414px]:w-5/6">
<Text className="text-[32rpx] min-[375px]:text-[34rpx]">适配不同屏幕</Text>
</View>
按钮组件样式:
// src/components/ui/button.tsx
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline: 'border border-input hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'underline-offset-4 hover:underline text-primary',
},
size: {
default: 'h-10 py-2 px-4',
sm: 'h-9 px-3 rounded-md text-xs',
lg: 'h-11 px-8 rounded-md',
icon: 'h-10 w-10',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
}
)
输入框组件:
// src/components/ui/input.tsx
const inputVariants = cva(
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
{
variants: {
variant: {
default: '',
search: 'pl-8',
},
},
defaultVariants: {
variant: 'default',
},
}
)
页面容器:
<View className="min-h-screen bg-gray-50">
{/* 安全区域适配 */}
<View className="safe-area">
{/* 内容容器 */}
<View className="container mx-auto px-4">
{/* 页面内容 */}
</View>
</View>
</View>
Flex布局:
<View className="flex flex-col space-y-4">
<View className="flex items-center justify-between">
<Text>左侧</Text>
<Text>右侧</Text>
</View>
<View className="flex-1">
<Text>自适应内容</Text>
</View>
</View>
网格系统:
<View className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<View className="bg-white p-4 rounded-lg shadow">卡片1</View>
<View className="bg-white p-4 rounded-lg shadow">卡片2</View>
<View className="bg-white p-4 rounded-lg shadow">卡片3</View>
</View>
文本颜色:
<Text className="text-primary">主要文本</Text>
<Text className="text-secondary">次要文本</Text>
<Text className="text-muted-foreground">弱化文本</Text>
<Text className="text-destructive">错误文本</Text>
背景颜色:
<View className="bg-background">页面背景</View>
<View className="bg-card">卡片背景</View>
<View className="bg-popover">弹出层背景</View>
<View className="bg-muted">弱化背景</View>
主要品牌色:
<Button className="bg-primary text-primary-foreground">主要按钮</Button>
<Text className="text-primary">品牌文字</Text>
<View className="border-primary">品牌边框</View>
状态颜色:
<View className="text-success">成功状态</View>
<View className="text-warning">警告状态</View>
<View className="text-error">错误状态</View>
<View className="text-info">信息状态</View>
垂直间距:
<View className="space-y-2"> {/* 小间距 */}
<View className="space-y-4"> {/* 中等间距 */}
<View className="space-y-6"> {/* 大间距 */}
<View className="space-y-8"> {/* 超大间距 */}
水平间距:
<View className="space-x-2"> {/* 小间距 */}
<View className="space-x-4"> {/* 中等间距 */}
<View className="space-x-6"> {/* 大间距 */}
固定尺寸:
<View className="w-16 h-16"> {/* 64px */}
<View className="w-24 h-24"> {/* 96px */}
<View className="w-32 h-32"> {/* 128px */}
相对尺寸:
<View className="w-1/2"> {/* 50%宽度 */}
<View className="w-full"> {/* 100%宽度 */}
<View className="w-auto"> {/* 自动宽度 */}
<View className="min-w-0"> {/* 最小宽度0 */}
文本层级:
<Text className="text-xs"> 辅助文本 (12px)</Text>
<Text className="text-sm"> 小文本 (14px)</Text>
<Text className="text-base">基础文本 (16px)</Text>
<Text className="text-lg"> 大文本 (18px)</Text>
<Text className="text-xl"> 标题文本 (20px)</Text>
<Text className="text-2xl"> 大标题 (24px)</Text>
字重层级:
<Text className="font-normal">正常</Text>
<Text className="font-medium">中等</Text>
<Text className="font-semibold">半粗</Text>
<Text className="font-bold">粗体</Text>
行高控制:
<Text className="leading-tight"> 紧密行高</Text>
<Text className="leading-normal"> 正常行高</Text>
<Text className="leading-relaxed">宽松行高</Text>
<Text className="leading-loose"> 超松行高</Text>
按钮悬停:
<Button className="bg-primary hover:bg-primary/90">
悬停变暗
</Button>
卡片悬停:
<View className="bg-white hover:bg-gray-50 transition-colors">
悬停变亮
</View>
输入框焦点:
<Input className="focus:ring-2 focus:ring-primary focus:border-transparent" />
按钮焦点:
<Button className="focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2">
焦点环
</Button>
按钮激活:
<Button className="active:scale-95 transition-transform">
点击缩放
</Button>
基础过渡:
<View className="transition-all duration-300 ease-in-out">
所有属性过渡
</View>
<View className="transition-colors duration-200">
颜色过渡
</View>
<View className="transition-transform duration-150">
变换过渡
</View>
缩放变换:
<View className="hover:scale-105 active:scale-95 transition-transform">
悬停放大,点击缩小
</View>
位移变换:
<View className="hover:-translate-y-1 transition-transform">
悬停上移
</View>
响应式单位:
<View className="w-[750rpx] h-[200rpx]">
<Text className="text-[32rpx]">使用rpx单位</Text>
</View>
iPhone安全区域:
<View className="pb-safe">
{/* 底部安全区域 */}
</View>
<View className="pt-safe">
{/* 顶部安全区域 */}
</View>
使用cn工具:
import { cn } from '@/utils/cn'
export function Component({ className, variant }) {
return (
<View className={cn(
'base-classes',
variant === 'primary' && 'primary-classes',
className
)}>
内容
</View>
)
}
作用域样式:
// 使用特定的前缀或命名空间
<View className="travel-home-page">
<Text className="travel-home-title">标题</Text>
</View>
文档状态: 正式版 下次评审: 2025-11-15