Appearance
TailwindCSS
简介
Tailwind CSS是一个功能类优先(utility-first)的CSS框架,它与传统的UI框架(如Bootstrap、Bulma等)不同,不提供预设的组件样式,而是提供大量的功能类(utility classes),让开发者可以直接在HTML中组合这些类来构建自定义设计,而无需编写CSS。
核心理念
功能类优先(Utility-First)
Tailwind的核心理念是通过组合小型、单一用途的功能类来构建界面,而不是通过预定义的组件类:
html
<!-- 传统CSS方式 -->
<button class="btn btn-primary">按钮</button>
<!-- Tailwind方式 -->
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
按钮
</button>响应式设计
Tailwind内置了一套响应式系统,可以轻松创建适应不同屏幕尺寸的界面:
html
<div class="text-center sm:text-left md:text-right lg:text-justify">
这段文本在不同屏幕尺寸下有不同的对齐方式
</div>状态变体
Tailwind提供了丰富的状态变体,如悬停、聚焦、激活等:
html
<button class="bg-blue-500 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-300 active:bg-blue-800">
交互按钮
</button>安装与配置
通过NPM安装
bash
# 安装Tailwind CSS
npm install -D tailwindcss
# 生成配置文件
npx tailwindcss init配置文件
javascript
// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{html,js,jsx,ts,tsx}',
],
theme: {
extend: {
colors: {
'brand': '#3490dc',
'brand-light': '#6cb2eb',
},
spacing: {
'72': '18rem',
'84': '21rem',
'96': '24rem',
},
fontFamily: {
'sans': ['Inter', 'sans-serif'],
},
},
},
plugins: [],
}在CSS中引入
css
/* src/styles.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* 自定义样式可以放在这里 */
@layer components {
.btn-primary {
@apply py-2 px-4 bg-blue-500 text-white font-semibold rounded-lg shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-75;
}
}构建过程
bash
# 使用CLI构建
npx tailwindcss -i ./src/styles.css -o ./dist/output.css --watch
# 或在package.json中添加脚本
"scripts": {
"dev": "tailwindcss -i ./src/styles.css -o ./dist/output.css --watch"
}核心功能类
布局
html
<!-- 容器 -->
<div class="container mx-auto px-4">
<!-- 内容 -->
</div>
<!-- 显示属性 -->
<div class="block sm:inline md:flex lg:grid">
<!-- 内容 -->
</div>
<!-- 定位 -->
<div class="relative">
<div class="absolute top-0 right-0">
<!-- 绝对定位元素 -->
</div>
</div>
<!-- Z-index -->
<div class="z-10"><!-- 内容 --></div>
<div class="z-20"><!-- 内容 --></div>排版
html
<!-- 字体系列 -->
<p class="font-sans">Sans-serif字体</p>
<p class="font-serif">Serif字体</p>
<p class="font-mono">等宽字体</p>
<!-- 字体大小 -->
<p class="text-xs">超小文本</p>
<p class="text-sm">小文本</p>
<p class="text-base">基础文本</p>
<p class="text-lg">大文本</p>
<p class="text-xl">超大文本</p>
<p class="text-2xl">2xl文本</p>
<!-- 更多尺寸... -->
<!-- 字体粗细 -->
<p class="font-thin">细体</p>
<p class="font-normal">常规</p>
<p class="font-medium">中等</p>
<p class="font-bold">粗体</p>
<!-- 文本对齐 -->
<p class="text-left">左对齐</p>
<p class="text-center">居中对齐</p>
<p class="text-right">右对齐</p>
<!-- 文本颜色 -->
<p class="text-blue-500">蓝色文本</p>
<p class="text-red-600">红色文本</p>背景
html
<!-- 背景颜色 -->
<div class="bg-white">白色背景</div>
<div class="bg-gray-100">浅灰色背景</div>
<div class="bg-blue-500">蓝色背景</div>
<!-- 背景渐变 -->
<div class="bg-gradient-to-r from-cyan-500 to-blue-500">
渐变背景
</div>
<!-- 背景图片 -->
<div class="bg-cover bg-center" style="background-image: url('/img/background.jpg')">
背景图片
</div>边框
html
<!-- 边框宽度 -->
<div class="border">默认边框</div>
<div class="border-2">宽边框</div>
<div class="border-4">更宽边框</div>
<!-- 边框颜色 -->
<div class="border border-blue-500">蓝色边框</div>
<div class="border border-red-500">红色边框</div>
<!-- 边框圆角 -->
<div class="rounded">圆角</div>
<div class="rounded-md">中等圆角</div>
<div class="rounded-lg">大圆角</div>
<div class="rounded-full">完全圆形</div>间距
html
<!-- 内边距 -->
<div class="p-4">所有方向内边距</div>
<div class="px-4">水平内边距</div>
<div class="py-4">垂直内边距</div>
<div class="pt-4">顶部内边距</div>
<div class="pr-4">右侧内边距</div>
<div class="pb-4">底部内边距</div>
<div class="pl-4">左侧内边距</div>
<!-- 外边距 -->
<div class="m-4">所有方向外边距</div>
<div class="mx-4">水平外边距</div>
<div class="my-4">垂直外边距</div>
<div class="mt-4">顶部外边距</div>
<div class="mr-4">右侧外边距</div>
<div class="mb-4">底部外边距</div>
<div class="ml-4">左侧外边距</div>
<!-- 自动外边距 -->
<div class="mx-auto">水平居中</div>Flexbox
html
<div class="flex flex-row justify-between items-center">
<div>项目1</div>
<div>项目2</div>
<div>项目3</div>
</div>
<!-- Flex方向 -->
<div class="flex flex-row">行方向</div>
<div class="flex flex-col">列方向</div>
<!-- 主轴对齐 -->
<div class="flex justify-start">起点对齐</div>
<div class="flex justify-center">居中对齐</div>
<div class="flex justify-end">终点对齐</div>
<div class="flex justify-between">两端对齐</div>
<div class="flex justify-around">环绕对齐</div>
<!-- 交叉轴对齐 -->
<div class="flex items-start">起点对齐</div>
<div class="flex items-center">居中对齐</div>
<div class="flex items-end">终点对齐</div>
<div class="flex items-stretch">拉伸对齐</div>
<!-- Flex项目 -->
<div class="flex">
<div class="flex-1">伸缩项目</div>
<div class="flex-none">不伸缩项目</div>
<div class="flex-grow">只增长项目</div>
<div class="flex-shrink">只收缩项目</div>
</div>Grid
html
<!-- 基本网格 -->
<div class="grid grid-cols-3 gap-4">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
<!-- 响应式网格 -->
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
<!-- 内容 -->
</div>
<!-- 网格跨列 -->
<div class="grid grid-cols-3 gap-4">
<div class="col-span-2">跨越2列</div>
<div>1列</div>
<div>1列</div>
<div class="col-span-3">跨越3列</div>
</div>自定义与扩展
使用@apply组合功能类
css
@layer components {
.card {
@apply bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow duration-300;
}
.btn {
@apply font-bold py-2 px-4 rounded;
}
.btn-blue {
@apply btn bg-blue-500 text-white hover:bg-blue-700;
}
.btn-gray {
@apply btn bg-gray-300 text-gray-700 hover:bg-gray-400;
}
}扩展主题
javascript
// tailwind.config.js
module.exports = {
theme: {
extend: {
// 扩展颜色
colors: {
'custom-blue': '#1da1f2',
'custom-green': '#17bf63',
},
// 扩展字体
fontFamily: {
'display': ['Poppins', 'sans-serif'],
'body': ['Roboto', 'sans-serif'],
},
// 扩展断点
screens: {
'3xl': '1600px',
},
// 扩展间距
spacing: {
'128': '32rem',
},
// 扩展阴影
boxShadow: {
'outline-blue': '0 0 0 3px rgba(66, 153, 225, 0.5)',
},
},
},
}创建插件
javascript
// tailwind.config.js
const plugin = require('tailwindcss/plugin')
module.exports = {
plugins: [
plugin(function({ addComponents, theme }) {
const buttons = {
'.btn': {
padding: `${theme('spacing.2')} ${theme('spacing.4')}`,
fontWeight: theme('fontWeight.bold'),
borderRadius: theme('borderRadius.default'),
'&:focus': {
outline: 'none',
boxShadow: theme('boxShadow.outline'),
},
},
'.btn-blue': {
backgroundColor: theme('colors.blue.500'),
color: theme('colors.white'),
'&:hover': {
backgroundColor: theme('colors.blue.600'),
},
},
}
addComponents(buttons)
}),
],
}优化生产环境
清除未使用的CSS
Tailwind默认使用PurgeCSS来移除生产环境中未使用的CSS类:
javascript
// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{html,js,jsx,ts,tsx,vue}',
],
// 其他配置...
}压缩CSS
bash
# 使用--minify选项
npx tailwindcss -i ./src/styles.css -o ./dist/output.css --minify与框架集成
React集成
jsx
// App.jsx
import React from 'react';
function App() {
return (
<div className="min-h-screen bg-gray-100 py-6 flex flex-col justify-center sm:py-12">
<div className="relative py-3 sm:max-w-xl sm:mx-auto">
<div className="absolute inset-0 bg-gradient-to-r from-cyan-400 to-light-blue-500 shadow-lg transform -skew-y-6 sm:skew-y-0 sm:-rotate-6 sm:rounded-3xl"></div>
<div className="relative px-4 py-10 bg-white shadow-lg sm:rounded-3xl sm:p-20">
<div className="max-w-md mx-auto">
<div className="text-center">
<h1 className="text-3xl font-extrabold text-gray-900">Tailwind CSS with React</h1>
<p className="mt-2 text-gray-600">使用Tailwind CSS构建React应用</p>
</div>
</div>
</div>
</div>
</div>
);
}
export default App;Vue集成
vue
<!-- App.vue -->
<template>
<div class="min-h-screen bg-gray-100 py-6 flex flex-col justify-center sm:py-12">
<div class="relative py-3 sm:max-w-xl sm:mx-auto">
<div class="absolute inset-0 bg-gradient-to-r from-cyan-400 to-light-blue-500 shadow-lg transform -skew-y-6 sm:skew-y-0 sm:-rotate-6 sm:rounded-3xl"></div>
<div class="relative px-4 py-10 bg-white shadow-lg sm:rounded-3xl sm:p-20">
<div class="max-w-md mx-auto">
<div class="text-center">
<h1 class="text-3xl font-extrabold text-gray-900">Tailwind CSS with Vue</h1>
<p class="mt-2 text-gray-600">使用Tailwind CSS构建Vue应用</p>
</div>
</div>
</div>
</div>
</div>
</template>最佳实践
组织大型项目
- 使用
@layer components创建可复用组件 - 使用
@apply提取重复的功能类组合 - 使用主题配置保持设计一致性
- 考虑使用组件库(如Headless UI)与Tailwind结合
响应式设计策略
- 采用移动优先的设计方法
- 使用响应式前缀(sm:, md:, lg:, xl:)逐步增强界面
- 避免在所有断点都重复定义相同的样式
性能优化
- 确保正确配置
content选项以清除未使用的CSS - 考虑使用
@apply减少HTML中的类名长度 - 在开发中使用JIT模式加快编译速度
与其他CSS方案对比
| 特性 | Tailwind CSS | Bootstrap | CSS-in-JS | 传统CSS |
|---|---|---|---|---|
| 学习曲线 | 中等 | 低 | 高 | 低-中 |
| 自定义性 | 高 | 中 | 高 | 高 |
| 开发速度 | 快 | 快 | 中 | 慢 |
| 文件大小 | 小(优化后) | 大 | 小-中 | 取决于项目 |
| 组件化 | 通过@apply | 预设组件 | 原生支持 | 需手动实现 |
| 主题支持 | 强大 | 有限 | 强大 | 需手动实现 |
| 类型安全 | 无 | 无 | 可能有 | 无 |
常见问题与解决方案
类名过长
html
<!-- 问题:类名过长难以维护 -->
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
按钮
</button>
<!-- 解决方案:使用@apply创建组件类 -->
<!-- 在CSS中 -->
@layer components {
.btn-primary {
@apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline;
}
}
<!-- 在HTML中 -->
<button class="btn-primary">按钮</button>条件样式
jsx
// React中的条件样式
function Button({ primary }) {
return (
<button
className={`
font-bold py-2 px-4 rounded
${primary ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-800'}
`}
>
按钮
</button>
);
}
// 使用库如classnames或clsx
import classNames from 'classnames';
function Button({ primary, disabled }) {
return (
<button
className={classNames(
'font-bold py-2 px-4 rounded',
{
'bg-blue-500 text-white': primary && !disabled,
'bg-gray-200 text-gray-800': !primary && !disabled,
'bg-gray-300 text-gray-500 cursor-not-allowed': disabled
}
)}
>
按钮
</button>
);
}