TailwindCSS 完全指南

相关文档:HTML与CSS入门(/html-yu-css-ru-men/) Vue3入门(/vue-3-ru-men-zhi-nan/) 1. Tailwind 是什么(#tailwind-%E6%98%AF%E4%BB%80%E4%B9%88) 2. 安装与配置(#%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE) 3. 核心工具类速查表(#%E6%A0%B8%E5%BF%83%E5%B7%A5%E5%85%B7%E7%B1%BB%E9%80%9F%E6%9F%A5%E8%A1%A8) 4. 自定义配置(#%E

分享

官方文档:https://tailwindcss.com/docs
适用版本:Tailwind CSS 4.x(2026-05-07 核实)

相关文档:HTML与CSS入门 Vue3入门


目录

  1. Tailwind 是什么
  2. 安装与配置
  3. 核心工具类速查表
  4. 自定义配置
  5. 最佳实践
  6. 100 个常用工具类速查表
  7. 综合实战示例

Tailwind 是什么

工具类优先(Utility-First)理念

Tailwind CSS 是一个工具类优先(Utility-First)的 CSS 框架。它不提供预先设计好的组件(如 Bootstrap 的 .btn.card),而是提供大量低层级的工具类,每个工具类只做一件事。

<!-- 传统 CSS 写法:需要自己起类名,跳转到 CSS 文件写样式 -->
<div class="card">...</div>

<!-- Bootstrap 写法:使用预设组件,样式固定,难以定制 -->
<div class="card p-3 shadow-sm">...</div>

<!-- Tailwind 写法:工具类直接描述样式,不需要额外 CSS 文件 -->
<div class="flex flex-col p-6 bg-white rounded-xl shadow-md">...</div>

与传统 CSS / Bootstrap 的对比

维度 传统 CSS Bootstrap Tailwind CSS
写法 自定义类名 + CSS 文件 预设组件类名 工具类直接写在 HTML
定制性 完全自由 需覆盖变量或重写 通过配置文件扩展
包体积 手写多少就多少 引入全部组件样式 PurgeCSS 按需打包
学习曲线 需要懂 CSS 记住组件名 需要记住工具类名
一致性 依赖开发者自律 组件一致 设计系统约束一致
响应式 手写 media query 内置断点类 前缀断点类(sm/md/lg)
暗色模式 手写 prefers-color-scheme 需额外插件 dark: 变体内置支持

核心优势:

  • 不需要在 HTML 和 CSS 文件之间来回切换
  • 不需要绞尽脑汁起类名
  • CSS 文件大小不随项目增长而无限膨胀(工具类是复用的)
  • 设计约束来自配置文件,全局一致

安装与配置

方式一:CDN(仅用于开发调试)

<!-- 在 <head> 中引入,无需安装,无法自定义配置 -->
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- Tailwind CSS v4 CDN(最新版本) -->
  <script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
  <h1 class="text-3xl font-bold text-blue-600">Hello Tailwind</h1>
</body>
</html>

注意:CDN 方式会加载完整的 Tailwind CSS(约 4MB),不适合生产环境。

方式二:Vite 项目集成(推荐)

# 创建 Vite 项目(以 Vue3 为例)
npm create vite@latest my-project -- --template vue
cd my-project

# 安装 Tailwind CSS 及依赖
npm install -D tailwindcss postcss autoprefixer

# 生成配置文件
npx tailwindcss init -p

生成的 postcss.config.js

// postcss.config.js
export default {
  plugins: {
    tailwindcss: {},   // 处理 Tailwind 指令
    autoprefixer: {},  // 自动添加浏览器前缀
  },
}

tailwind.config.js 中配置内容扫描路径:

// tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  // content:告诉 Tailwind 扫描哪些文件,提取使用到的工具类
  content: [
    "./index.html",
    "./src/**/*.{vue,js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

在主 CSS 文件中引入 Tailwind 指令:

/* src/style.css 或 src/assets/main.css */

/* 引入 Tailwind 的基础样式(reset + 基础排版) */
@tailwind base;

/* 引入所有工具类 */
@tailwind components;

/* 引入所有工具类 */
@tailwind utilities;

main.js 中引入 CSS:

// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import './style.css'  // 引入包含 Tailwind 指令的 CSS 文件

createApp(App).mount('#app')

方式三:PostCSS 配置(非 Vite 项目)

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init

在构建工具(Webpack/Rollup 等)的 PostCSS 配置中添加 Tailwind 插件,与方式二类似。

tailwind.config.js 完整结构说明

// tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  // content:文件扫描路径,Tailwind 会从这些文件中提取用到的类名
  // 生产构建时会删除未使用的工具类
  content: [
    "./index.html",
    "./src/**/*.{vue,js,ts,jsx,tsx,html}",
  ],

  // darkMode:暗色模式策略
  // 'media'  → 跟随系统 prefers-color-scheme(默认)
  // 'class'  → 手动在 <html> 上添加 .dark 类来切换
  darkMode: 'class',

  theme: {
    // theme 直接赋值会覆盖默认主题(谨慎使用)
    // fontFamily: { sans: ['Arial', 'sans-serif'] }  // 完全替换字体

    // extend 在默认主题基础上追加,推荐使用
    extend: {
      colors: {
        brand: {
          50:  '#eff6ff',
          500: '#3b82f6',
          900: '#1e3a8a',
        },
      },
      fontFamily: {
        custom: ['"Microsoft YaHei"', 'sans-serif'],
      },
      spacing: {
        '18': '4.5rem',   // 追加 m-18, p-18 等工具类
        '72': '18rem',
      },
      borderRadius: {
        '4xl': '2rem',
      },
      screens: {
        'xs': '475px',   // 追加 xs: 断点
      },
    },
  },

  // plugins:引入第三方插件
  plugins: [
    // require('@tailwindcss/forms'),       // 表单样式重置
    // require('@tailwindcss/typography'),  // 文章排版(prose 类)
    // require('@tailwindcss/aspect-ratio'),
  ],
}

核心工具类速查表

布局

Container

类名 说明
container 设置 max-width 并自动响应断点,需配合 mx-auto 居中
<div class="container mx-auto px-4">
  <!-- 内容区域,居中且两侧有内边距 -->
</div>

Box Sizing

类名 CSS 等价
box-border box-sizing: border-box
box-content box-sizing: content-box

Display

类名 CSS 等价
block display: block
inline display: inline
inline-block display: inline-block
flex display: flex
inline-flex display: inline-flex
grid display: grid
inline-grid display: inline-grid
hidden display: none
table display: table
table-cell display: table-cell
contents display: contents

Overflow

类名 CSS 等价
overflow-auto overflow: auto
overflow-hidden overflow: hidden
overflow-visible overflow: visible
overflow-scroll overflow: scroll
overflow-x-auto overflow-x: auto
overflow-y-auto overflow-y: auto
overflow-x-hidden overflow-x: hidden
truncate 单行文字截断(overflow-hidden + text-ellipsis + whitespace-nowrap)

Position

类名 CSS 等价
static position: static
relative position: relative
absolute position: absolute
fixed position: fixed
sticky position: sticky

定位偏移(与 position 配合使用):

类名 CSS 等价
top-0 top: 0
top-4 top: 1rem
right-0 right: 0
bottom-0 bottom: 0
left-0 left: 0
inset-0 top/right/bottom/left: 0(常用于覆盖层)
inset-x-0 left: 0; right: 0
inset-y-0 top: 0; bottom: 0
top-1/2 top: 50%(配合 -translate-y-1/2 垂直居中)

Z-Index

类名 CSS 等价
z-0 z-index: 0
z-10 z-index: 10
z-20 z-index: 20
z-30 z-index: 30
z-40 z-index: 40
z-50 z-index: 50
z-auto z-index: auto
-z-10 z-index: -10

Flexbox

<!-- 基础 Flex 容器 -->
<div class="flex items-center justify-between gap-4">
  <div>左侧内容</div>
  <div>右侧内容</div>
</div>

flex-direction(主轴方向)

类名 CSS 等价
flex-row flex-direction: row(默认,水平从左到右)
flex-row-reverse flex-direction: row-reverse
flex-col flex-direction: column(垂直从上到下)
flex-col-reverse flex-direction: column-reverse

justify-content(主轴对齐)

类名 CSS 等价
justify-start justify-content: flex-start
justify-end justify-content: flex-end
justify-center justify-content: center
justify-between justify-content: space-between
justify-around justify-content: space-around
justify-evenly justify-content: space-evenly

align-items(交叉轴对齐)

类名 CSS 等价
items-start align-items: flex-start
items-end align-items: flex-end
items-center align-items: center
items-baseline align-items: baseline
items-stretch align-items: stretch

align-self(单个子项交叉轴对齐)

类名 CSS 等价
self-auto align-self: auto
self-start align-self: flex-start
self-end align-self: flex-end
self-center align-self: center
self-stretch align-self: stretch

flex-wrap

类名 CSS 等价
flex-nowrap flex-wrap: nowrap(默认)
flex-wrap flex-wrap: wrap
flex-wrap-reverse flex-wrap: wrap-reverse

gap(间距)

类名 CSS 等价
gap-0 gap: 0
gap-1 gap: 0.25rem
gap-2 gap: 0.5rem
gap-4 gap: 1rem
gap-6 gap: 1.5rem
gap-8 gap: 2rem
gap-x-4 column-gap: 1rem
gap-y-4 row-gap: 1rem

flex-grow / flex-shrink

类名 CSS 等价
flex-1 flex: 1 1 0%(等比分配剩余空间)
flex-auto flex: 1 1 auto
flex-none flex: none(不参与弹性计算)
grow flex-grow: 1
grow-0 flex-grow: 0
shrink flex-shrink: 1
shrink-0 flex-shrink: 0(不压缩,常用于固定宽度元素)

order(排列顺序)

类名 CSS 等价
order-first order: -9999
order-last order: 9999
order-none order: 0
order-1 ~ order-12 order: 1 ~ order: 12

Grid

<!-- 三列等宽网格,间距 1rem -->
<div class="grid grid-cols-3 gap-4">
  <div>列1</div>
  <div>列2</div>
  <div>列3</div>
</div>

grid-cols(列数)

类名 CSS 等价
grid-cols-1 grid-template-columns: repeat(1, minmax(0, 1fr))
grid-cols-2 grid-template-columns: repeat(2, minmax(0, 1fr))
grid-cols-3 grid-template-columns: repeat(3, minmax(0, 1fr))
grid-cols-4 grid-template-columns: repeat(4, minmax(0, 1fr))
grid-cols-6 grid-template-columns: repeat(6, minmax(0, 1fr))
grid-cols-12 grid-template-columns: repeat(12, minmax(0, 1fr))
grid-cols-none grid-template-columns: none

col-span(列跨越)

类名 CSS 等价
col-span-1 grid-column: span 1 / span 1
col-span-2 grid-column: span 2 / span 2
col-span-3 grid-column: span 3 / span 3
col-span-full grid-column: 1 / -1(跨越所有列)
col-start-1 grid-column-start: 1
col-end-4 grid-column-end: 4

grid-rows(行数)

类名 CSS 等价
grid-rows-1 grid-template-rows: repeat(1, minmax(0, 1fr))
grid-rows-3 grid-template-rows: repeat(3, minmax(0, 1fr))
grid-rows-6 grid-template-rows: repeat(6, minmax(0, 1fr))

row-span(行跨越)

类名 CSS 等价
row-span-1 grid-row: span 1 / span 1
row-span-2 grid-row: span 2 / span 2
row-span-full grid-row: 1 / -1

Spacing(间距)

间距尺寸表

比例值 N rem 值 px 值(16px 基准)
0 0 0
0.5 0.125rem 2px
1 0.25rem 4px
1.5 0.375rem 6px
2 0.5rem 8px
2.5 0.625rem 10px
3 0.75rem 12px
3.5 0.875rem 14px
4 1rem 16px
5 1.25rem 20px
6 1.5rem 24px
7 1.75rem 28px
8 2rem 32px
9 2.25rem 36px
10 2.5rem 40px
11 2.75rem 44px
12 3rem 48px
14 3.5rem 56px
16 4rem 64px
20 5rem 80px
24 6rem 96px
28 7rem 112px
32 8rem 128px
36 9rem 144px
40 10rem 160px
44 11rem 176px
48 12rem 192px
52 13rem 208px
56 14rem 224px
60 15rem 240px
64 16rem 256px
72 18rem 288px
80 20rem 320px
96 24rem 384px

Margin 工具类

类名 说明
m-{N} 四边 margin
mx-{N} 水平方向 margin(left + right)
my-{N} 垂直方向 margin(top + bottom)
mt-{N} margin-top
mb-{N} margin-bottom
ml-{N} margin-left
mr-{N} margin-right
ms-{N} margin-inline-start(支持 RTL)
me-{N} margin-inline-end(支持 RTL)
mx-auto 水平居中(margin-left/right: auto)
-m-{N} 负 margin(如 -m-4)

Padding 工具类

类名 说明
p-{N} 四边 padding
px-{N} 水平方向 padding(left + right)
py-{N} 垂直方向 padding(top + bottom)
pt-{N} padding-top
pb-{N} padding-bottom
pl-{N} padding-left
pr-{N} padding-right

Sizing(尺寸)

Width

类名 CSS 等价
w-0 width: 0
w-{N} width: {N 对应的 rem 值}
w-auto width: auto
w-full width: 100%
w-screen width: 100vw
w-svw width: 100svw(small viewport)
w-fit width: fit-content
w-min width: min-content
w-max width: max-content
w-1/2 width: 50%
w-1/3 width: 33.333%
w-2/3 width: 66.667%
w-1/4 width: 25%
w-3/4 width: 75%

Max-Width / Min-Width

类名 CSS 等价
max-w-xs max-width: 20rem(320px)
max-w-sm max-width: 24rem(384px)
max-w-md max-width: 28rem(448px)
max-w-lg max-width: 32rem(512px)
max-w-xl max-width: 36rem(576px)
max-w-2xl max-width: 42rem(672px)
max-w-3xl max-width: 48rem(768px)
max-w-4xl max-width: 56rem(896px)
max-w-5xl max-width: 64rem(1024px)
max-w-6xl max-width: 72rem(1152px)
max-w-7xl max-width: 80rem(1280px)
max-w-full max-width: 100%
max-w-screen-sm max-width: 640px
max-w-screen-lg max-width: 1024px
min-w-0 min-width: 0
min-w-full min-width: 100%

Height

类名 CSS 等价
h-{N} height: {N 对应的 rem 值}
h-auto height: auto
h-full height: 100%
h-screen height: 100vh
h-svh height: 100svh
h-dvh height: 100dvh(动态视口,推荐移动端)
h-fit height: fit-content
h-min height: min-content
h-max height: max-content
min-h-0 min-height: 0
min-h-full min-height: 100%
min-h-screen min-height: 100vh
max-h-full max-height: 100%
max-h-screen max-height: 100vh

Typography(排版)

Font Size

类名 font-size line-height
text-xs 0.75rem (12px) 1rem
text-sm 0.875rem (14px) 1.25rem
text-base 1rem (16px) 1.5rem
text-lg 1.125rem (18px) 1.75rem
text-xl 1.25rem (20px) 1.75rem
text-2xl 1.5rem (24px) 2rem
text-3xl 1.875rem (30px) 2.25rem
text-4xl 2.25rem (36px) 2.5rem
text-5xl 3rem (48px) 1
text-6xl 3.75rem (60px) 1
text-7xl 4.5rem (72px) 1
text-8xl 6rem (96px) 1
text-9xl 8rem (128px) 1

Font Weight

类名 font-weight
font-thin 100
font-extralight 200
font-light 300
font-normal 400
font-medium 500
font-semibold 600
font-bold 700
font-extrabold 800
font-black 900

Font Family

类名 CSS 等价
font-sans 系统 sans-serif 字体栈
font-serif 系统 serif 字体栈
font-mono 系统等宽字体栈

Text Align

类名 CSS 等价
text-left text-align: left
text-center text-align: center
text-right text-align: right
text-justify text-align: justify

Text Color

颜色格式:text-{color}-{shade},shade 范围 50/100/200/300/400/500/600/700/800/900/950

<!-- 常用颜色示例 -->
<p class="text-gray-500">灰色文字</p>
<p class="text-blue-600">蓝色文字</p>
<p class="text-red-500">红色文字</p>
<p class="text-green-700">深绿文字</p>
<p class="text-white">白色文字</p>
<p class="text-black">黑色文字</p>
<p class="text-transparent">透明文字</p>

内置颜色:slate / gray / zinc / neutral / stone / red / orange / amber / yellow / lime / green / emerald / teal / cyan / sky / blue / indigo / violet / purple / fuchsia / pink / rose

Line Height(leading)

类名 line-height
leading-none 1
leading-tight 1.25
leading-snug 1.375
leading-normal 1.5
leading-relaxed 1.625
leading-loose 2
leading-3 0.75rem
leading-4 1rem
leading-5 1.25rem

Letter Spacing(tracking)

类名 letter-spacing
tracking-tighter -0.05em
tracking-tight -0.025em
tracking-normal 0em
tracking-wide 0.025em
tracking-wider 0.05em
tracking-widest 0.1em

Text Decoration

类名 CSS 等价
underline text-decoration: underline
overline text-decoration: overline
line-through text-decoration: line-through
no-underline text-decoration: none

Text Transform

类名 CSS 等价
uppercase text-transform: uppercase
lowercase text-transform: lowercase
capitalize text-transform: capitalize
normal-case text-transform: none

Whitespace & Word Break

类名 CSS 等价
whitespace-normal white-space: normal
whitespace-nowrap white-space: nowrap
whitespace-pre white-space: pre
whitespace-pre-wrap white-space: pre-wrap
break-normal overflow-wrap: normal
break-words overflow-wrap: break-word
break-all word-break: break-all

Background(背景)

Background Color

<div class="bg-blue-500">蓝色背景</div>
<div class="bg-gray-100">浅灰背景</div>
<div class="bg-white">白色背景</div>
<div class="bg-transparent">透明背景</div>

格式:bg-{color}-{shade},与文字颜色体系一致。

Background Opacity(Tailwind v3 用法)

<!-- v3 中通过 / 语法设置透明度 -->
<div class="bg-blue-500/50">50% 透明度的蓝色背景</div>
<div class="bg-black/30">30% 透明度的黑色(常用于遮罩层)</div>

Background Gradient

<!-- 水平渐变:左到右 -->
<div class="bg-gradient-to-r from-blue-500 to-purple-600">渐变背景</div>

<!-- 三色渐变:含中间色 -->
<div class="bg-gradient-to-r from-pink-500 via-red-500 to-yellow-500">三色渐变</div>

<!-- 对角线渐变 -->
<div class="bg-gradient-to-br from-green-400 to-blue-500">对角渐变</div>

渐变方向:to-t(上)/ to-tr(右上)/ to-r(右)/ to-br(右下)/ to-b(下)/ to-bl(左下)/ to-l(左)/ to-tl(左上)

Background Size / Position

类名 CSS 等价
bg-auto background-size: auto
bg-cover background-size: cover
bg-contain background-size: contain
bg-center background-position: center
bg-top background-position: top
bg-bottom background-position: bottom
bg-left background-position: left
bg-right background-position: right
bg-no-repeat background-repeat: no-repeat

Border(边框)

Border Width

类名 CSS 等价
border border-width: 1px
border-0 border-width: 0
border-2 border-width: 2px
border-4 border-width: 4px
border-8 border-width: 8px
border-t border-top-width: 1px
border-b border-bottom-width: 1px
border-l border-left-width: 1px
border-r border-right-width: 1px
border-x 左右各 1px
border-y 上下各 1px

Border Color

<div class="border border-gray-300">灰色边框</div>
<div class="border-2 border-blue-500">蓝色边框</div>

格式:border-{color}-{shade}

Border Style

类名 CSS 等价
border-solid border-style: solid
border-dashed border-style: dashed
border-dotted border-style: dotted
border-double border-style: double
border-none border-style: none

Border Radius(圆角)

类名 CSS 等价
rounded-none border-radius: 0
rounded-sm border-radius: 0.125rem
rounded border-radius: 0.25rem
rounded-md border-radius: 0.375rem
rounded-lg border-radius: 0.5rem
rounded-xl border-radius: 0.75rem
rounded-2xl border-radius: 1rem
rounded-3xl border-radius: 1.5rem
rounded-full border-radius: 9999px(圆形/胶囊)
rounded-t-lg 上方两角
rounded-b-lg 下方两角
rounded-l-lg 左侧两角
rounded-r-lg 右侧两角
rounded-tl-lg 左上角
rounded-tr-lg 右上角

Outline

类名 CSS 等价
outline outline-style: solid
outline-none outline: 2px solid transparent(消除默认轮廓)
outline-dashed outline-style: dashed
outline-2 outline-width: 2px
outline-offset-2 outline-offset: 2px

Effects(效果)

Box Shadow

类名 说明
shadow-sm 细微阴影
shadow 基础阴影
shadow-md 中等阴影
shadow-lg 较大阴影
shadow-xl 大阴影
shadow-2xl 超大阴影
shadow-inner 内阴影
shadow-none 无阴影

Opacity

类名 CSS 等价
opacity-0 opacity: 0
opacity-5 opacity: 0.05
opacity-10 opacity: 0.1
opacity-25 opacity: 0.25
opacity-50 opacity: 0.5
opacity-75 opacity: 0.75
opacity-90 opacity: 0.9
opacity-100 opacity: 1

Ring(焦点轮廓,常用于交互反馈)

类名 说明
ring 3px 蓝色轮廓(box-shadow 实现)
ring-0 无轮廓
ring-1 1px 轮廓
ring-2 2px 轮廓
ring-4 4px 轮廓
ring-blue-500 蓝色轮廓
ring-offset-2 轮廓与元素间距 2px

Transitions & Animation(过渡与动画)

Transition

类名 说明
transition 过渡 color/background/border/opacity/box-shadow/transform
transition-all 过渡所有可动画属性
transition-colors 仅过渡颜色相关属性
transition-opacity 仅过渡透明度
transition-transform 仅过渡变换
transition-none 禁用过渡

Duration(过渡时长)

类名 CSS 等价
duration-75 transition-duration: 75ms
duration-100 transition-duration: 100ms
duration-150 transition-duration: 150ms
duration-200 transition-duration: 200ms
duration-300 transition-duration: 300ms
duration-500 transition-duration: 500ms
duration-700 transition-duration: 700ms
duration-1000 transition-duration: 1000ms

Easing(缓动函数)

类名 CSS 等价
ease-linear transition-timing-function: linear
ease-in transition-timing-function: cubic-bezier(0.4, 0, 1, 1)
ease-out transition-timing-function: cubic-bezier(0, 0, 0.2, 1)
ease-in-out transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1)

Transform(变换)

类名 CSS 等价
scale-0 transform: scale(0)
scale-50 transform: scale(0.5)
scale-100 transform: scale(1)
scale-105 transform: scale(1.05)
scale-110 transform: scale(1.1)
rotate-0 transform: rotate(0deg)
rotate-45 transform: rotate(45deg)
rotate-90 transform: rotate(90deg)
rotate-180 transform: rotate(180deg)
translate-x-4 transform: translateX(1rem)
translate-y-4 transform: translateY(1rem)
-translate-y-1/2 transform: translateY(-50%)(垂直居中常用)
skew-x-6 transform: skewX(6deg)

Animation(预设动画)

类名 效果
animate-spin 持续旋转(常用于加载图标)
animate-ping 扩散消失(常用于通知红点)
animate-pulse 呼吸明暗(常用于骨架屏)
animate-bounce 上下弹跳
animate-none 禁用动画
<!-- 加载中旋转图标 -->
<svg class="animate-spin h-5 w-5 text-blue-500" viewBox="0 0 24 24">...</svg>

<!-- 骨架屏占位 -->
<div class="animate-pulse bg-gray-200 h-4 w-full rounded"></div>

Interactivity(交互)

Cursor

类名 CSS 等价
cursor-auto cursor: auto
cursor-default cursor: default
cursor-pointer cursor: pointer(手型)
cursor-wait cursor: wait
cursor-text cursor: text
cursor-move cursor: move
cursor-not-allowed cursor: not-allowed
cursor-grab cursor: grab
cursor-grabbing cursor: grabbing

User Select

类名 CSS 等价
select-none user-select: none
select-text user-select: text
select-all user-select: all
select-auto user-select: auto

Pointer Events

类名 CSS 等价
pointer-events-none pointer-events: none(穿透点击)
pointer-events-auto pointer-events: auto

响应式前缀(断点)

Tailwind 采用移动端优先策略:不加前缀 = 所有屏幕,加前缀 = 该断点及以上。

断点表格

前缀 最小宽度 对应设备参考
无前缀 0px 手机(移动端优先基础样式)
sm: 640px 大屏手机 / 小平板
md: 768px 平板
lg: 1024px 笔记本
xl: 1280px 桌面显示器
2xl: 1536px 大型显示器
<!-- 移动端单列,平板两列,桌面四列 -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
  ...
</div>

<!-- 移动端隐藏,桌面显示 -->
<div class="hidden lg:block">仅桌面可见</div>

<!-- 移动端显示,桌面隐藏 -->
<div class="block lg:hidden">仅移动端可见</div>

<!-- 响应式文字大小 -->
<h1 class="text-2xl md:text-4xl lg:text-6xl">标题</h1>

状态变体(State Variants)

格式:{变体}:{工具类},可叠加多个变体。

常用状态变体

变体 触发条件
hover: 鼠标悬停
focus: 元素获得焦点
focus-within: 子元素获得焦点
focus-visible: 键盘焦点(非鼠标)
active: 鼠标按下
visited: 链接已访问
disabled: 元素被禁用
checked: checkbox/radio 被选中
placeholder: input 的占位符
required: 必填表单元素
invalid: 验证失败的表单元素
valid: 验证通过的表单元素
dark: 暗色模式
print: 打印时
<!-- hover 改变背景色,focus 显示轮廓 -->
<button class="bg-blue-500 hover:bg-blue-700 focus:ring-2 focus:ring-blue-300 transition-colors">
  按钮
</button>

<!-- disabled 状态样式 -->
<button class="bg-blue-500 disabled:bg-gray-300 disabled:cursor-not-allowed" disabled>
  禁用按钮
</button>

<!-- 暗色模式 -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
  自适应明暗模式
</div>

Group 变体(父级悬停影响子级)

<!-- group-hover:父元素 hover 时,子元素响应变化 -->
<div class="group flex items-center gap-3 p-4 hover:bg-blue-50 rounded-lg cursor-pointer">
  <div class="text-gray-600 group-hover:text-blue-600">
    图标区域
  </div>
  <div class="text-sm text-gray-500 group-hover:text-blue-800">
    文字描述
  </div>
</div>

Peer 变体(兄弟元素状态影响当前元素)

<!-- peer-focus:前一个兄弟元素获得焦点时,当前元素响应 -->
<input class="peer border rounded px-3 py-2" type="email" placeholder="输入邮箱">
<p class="hidden peer-invalid:block text-red-500 text-sm">邮箱格式不正确</p>

伪元素变体

变体 说明
before: ::before 伪元素
after: ::after 伪元素
first: 第一个子元素
last: 最后一个子元素
odd: 奇数子元素
even: 偶数子元素
first-of-type: 同类型第一个
last-of-type: 同类型最后一个
only-child: 唯一子元素
placeholder: input 占位符样式
selection: 用户选中的文字
<!-- before/after 伪元素需要加 content-[''] -->
<div class="before:content-[''] before:block before:w-4 before:h-4 before:bg-blue-500">
  带前置装饰的元素
</div>

<!-- 列表斑马纹 -->
<ul>
  <li class="odd:bg-gray-50 even:bg-white px-4 py-2">奇数行</li>
  <li class="odd:bg-gray-50 even:bg-white px-4 py-2">偶数行</li>
</ul>

<!-- 去除最后一个子元素的边框 -->
<div class="last:border-b-0 border-b border-gray-200 py-3">列表项</div>

自定义配置

扩展主题(extend)

// tailwind.config.js
export default {
  theme: {
    extend: {
      // 扩展颜色(追加,不替换默认颜色)
      colors: {
        brand: {
          light: '#60a5fa',
          DEFAULT: '#3b82f6',  // 使用时写 text-brand(无需加 -DEFAULT)
          dark: '#1d4ed8',
        },
        'custom-gray': '#6b7280',
      },

      // 扩展字体
      fontFamily: {
        heading: ['"Noto Serif SC"', 'serif'],
        body: ['"Noto Sans SC"', 'sans-serif'],
      },

      // 扩展间距(追加到默认间距尺寸中)
      spacing: {
        '13': '3.25rem',
        '15': '3.75rem',
        '128': '32rem',
        '144': '36rem',
      },

      // 扩展断点
      screens: {
        'xs': '475px',
        '3xl': '1920px',
      },

      // 扩展圆角
      borderRadius: {
        '4xl': '2rem',
        '5xl': '2.5rem',
      },

      // 扩展阴影
      boxShadow: {
        'card': '0 2px 8px rgba(0, 0, 0, 0.08)',
        'popup': '0 10px 40px rgba(0, 0, 0, 0.16)',
      },

      // 扩展 z-index
      zIndex: {
        '60': '60',
        '70': '70',
        '80': '80',
        '90': '90',
        '100': '100',
      },

      // 扩展动画
      animation: {
        'fade-in': 'fadeIn 0.3s ease-in-out',
        'slide-up': 'slideUp 0.3s ease-out',
      },

      // 扩展 keyframes(配合 animation 使用)
      keyframes: {
        fadeIn: {
          '0%': { opacity: '0' },
          '100%': { opacity: '1' },
        },
        slideUp: {
          '0%': { transform: 'translateY(10px)', opacity: '0' },
          '100%': { transform: 'translateY(0)', opacity: '1' },
        },
      },
    },
  },
}

@layer 指令

@layer 将自定义样式注入到 Tailwind 的层级中,确保正确的优先级顺序。

/* src/style.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

/* @layer base:基础重置样式,优先级最低 */
@layer base {
  /* 全局字体设置 */
  html {
    font-family: "Noto Sans SC", sans-serif;
  }

  /* 重置标题样式 */
  h1, h2, h3, h4, h5, h6 {
    @apply font-bold leading-tight;
  }

  /* 重置链接样式 */
  a {
    @apply text-blue-600 hover:text-blue-800 transition-colors;
  }
}

/* @layer components:组件级样式,可被工具类覆盖 */
@layer components {
  /* 使用 @apply 抽取重复的工具类组合 */
  .btn {
    @apply inline-flex items-center justify-center px-4 py-2 rounded-lg font-medium transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2;
  }

  .btn-primary {
    @apply btn bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500;
  }

  .btn-secondary {
    @apply btn bg-gray-100 text-gray-700 hover:bg-gray-200 focus:ring-gray-400;
  }

  .card {
    @apply bg-white rounded-xl shadow-md overflow-hidden;
  }

  .input {
    @apply w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition;
  }
}

/* @layer utilities:自定义工具类,优先级最高 */
@layer utilities {
  /* 自定义工具类,可被响应式/状态变体修饰 */
  .text-balance {
    text-wrap: balance;
  }

  .scrollbar-hide {
    -ms-overflow-style: none;
    scrollbar-width: none;
  }

  .scrollbar-hide::-webkit-scrollbar {
    display: none;
  }
}

@apply 抽取可复用样式

/* 将常用的工具类组合提取为语义化类名 */
@layer components {
  /* 导航栏链接 */
  .nav-link {
    @apply text-gray-600 hover:text-blue-600 font-medium px-3 py-2 rounded-md transition-colors duration-150;
  }

  /* 标签/徽章 */
  .badge {
    @apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium;
  }

  .badge-blue {
    @apply badge bg-blue-100 text-blue-800;
  }

  .badge-green {
    @apply badge bg-green-100 text-green-800;
  }
}

注意事项:

  • @apply 会在构建时内联展开,不会生成额外的 CSS 类引用
  • 避免用 @apply 复制大量工具类,应优先通过组件化解决复用问题
  • @apply 只能在 CSS 文件中使用,不能在 style 属性中使用

Arbitrary Values(任意值)

当预设值不满足需求时,使用方括号语法输入任意值:

<!-- 任意宽度 -->
<div class="w-[200px]">固定 200px 宽度</div>
<div class="w-[calc(100%-2rem)]">计算宽度</div>

<!-- 任意颜色 -->
<p class="text-[#ff6b6b]">自定义红色文字</p>
<div class="bg-[rgb(59,130,246)]">自定义背景色</div>

<!-- 任意字体大小 -->
<p class="text-[13px]">13px 字体</p>

<!-- 任意 z-index -->
<div class="z-[999]">高层级定位</div>

<!-- 任意网格列定义 -->
<div class="grid grid-cols-[200px_1fr_auto]">不等宽三列</div>

<!-- 任意行高 -->
<p class="leading-[1.8]">1.8 倍行高</p>

<!-- CSS 变量 -->
<div class="bg-[var(--primary-color)]">使用 CSS 变量</div>

最佳实践

组件化:避免重复的工具类堆叠

<!-- 不推荐:同样的按钮样式散落在各处 -->
<template>
  <button class="inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">提交</button>
  <button class="inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">确认</button>
</template>

<!-- 推荐方案一:封装为 Vue 组件 -->
<!-- components/BaseButton.vue -->
<template>
  <button
    :class="[
      'inline-flex items-center justify-center px-4 py-2 rounded-lg font-medium transition-colors',
      variants[variant],
      sizes[size],
      { 'opacity-50 cursor-not-allowed': disabled }
    ]"
    :disabled="disabled"
  >
    <slot />
  </button>
</template>

<script setup>
defineProps({
  variant: { type: String, default: 'primary' },
  size:    { type: String, default: 'md' },
  disabled: { type: Boolean, default: false },
})

const variants = {
  primary:   'bg-blue-600 text-white hover:bg-blue-700 focus:ring-2 focus:ring-blue-500',
  secondary: 'bg-gray-100 text-gray-700 hover:bg-gray-200',
  danger:    'bg-red-600 text-white hover:bg-red-700',
  ghost:     'text-gray-700 hover:bg-gray-100',
}

const sizes = {
  sm: 'text-sm px-3 py-1.5',
  md: 'text-base px-4 py-2',
  lg: 'text-lg px-6 py-3',
}
</script>

<!-- 推荐方案二:在 CSS 中用 @apply 提取 -->
/* @layer components { .btn-primary { @apply ... } } */

暗色模式

class 策略(推荐,可手动切换):

// tailwind.config.js
export default {
  darkMode: 'class',  // 通过 .dark 类控制
  // ...
}
// 切换暗色模式
function toggleDarkMode() {
  document.documentElement.classList.toggle('dark')
  // 持久化到 localStorage
  localStorage.setItem('theme',
    document.documentElement.classList.contains('dark') ? 'dark' : 'light'
  )
}

// 初始化时读取用户偏好
const savedTheme = localStorage.getItem('theme')
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
  document.documentElement.classList.add('dark')
}
<!-- 同时支持明暗模式的组件 -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-300">
  <nav class="border-b border-gray-200 dark:border-gray-700">
    <a class="text-gray-600 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400">链接</a>
  </nav>
</div>

media 策略(跟随系统,无法手动切换):

// tailwind.config.js
export default {
  darkMode: 'media',  // 跟随系统 prefers-color-scheme
}

响应式设计:移动端优先

<!-- 正确:从最小屏开始,逐步增强 -->
<div class="
  flex flex-col gap-4
  md:flex-row md:gap-6
  lg:gap-8
">
  <aside class="w-full md:w-64 lg:w-80">侧边栏</aside>
  <main class="flex-1">主内容</main>
</div>

<!-- 正确:图片在移动端全宽,桌面端固定宽度 -->
<img class="w-full lg:w-1/2">

<!-- 错误:先写桌面样式再覆盖移动端(反向覆盖难维护)-->
<!-- <div class="flex-row max-sm:flex-col"> 不推荐这种反向覆盖 -->

与 Vue3 结合的动态 class 绑定

<template>
  <!-- 方式一:三元表达式 -->
  <div :class="isActive ? 'bg-blue-500 text-white' : 'bg-gray-100 text-gray-700'">
    状态切换
  </div>

  <!-- 方式二:对象语法 -->
  <div :class="{
    'bg-blue-500': isActive,
    'text-white': isActive,
    'opacity-50': isLoading,
    'cursor-not-allowed': disabled,
  }">
    复杂状态
  </div>

  <!-- 方式三:数组语法(推荐,清晰) -->
  <div :class="[
    'base-class px-4 py-2 rounded-lg',
    isActive ? 'bg-blue-500 text-white' : 'bg-gray-100',
    { 'opacity-50': isLoading },
  ]">
    数组写法
  </div>

  <!-- 方式四:计算属性(最佳实践,逻辑与模板分离) -->
  <button :class="buttonClasses">提交</button>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  variant: String,
  size: String,
  disabled: Boolean,
})

// 将复杂的 class 逻辑提取到计算属性中
const buttonClasses = computed(() => {
  const base = 'inline-flex items-center justify-center font-medium rounded-lg transition-colors'
  const variantMap = {
    primary: 'bg-blue-600 text-white hover:bg-blue-700',
    secondary: 'bg-gray-100 text-gray-700 hover:bg-gray-200',
  }
  const sizeMap = {
    sm: 'text-sm px-3 py-1.5',
    md: 'px-4 py-2',
    lg: 'text-lg px-6 py-3',
  }
  return [
    base,
    variantMap[props.variant] ?? variantMap.primary,
    sizeMap[props.size] ?? sizeMap.md,
    props.disabled ? 'opacity-50 cursor-not-allowed pointer-events-none' : '',
  ]
})
</script>

生产环境:PurgeCSS / content 配置

Tailwind 通过扫描 content 配置的文件来确定哪些工具类被用到,未使用的类在生产构建时会被删除。

// tailwind.config.js
export default {
  content: [
    "./index.html",
    "./src/**/*.{vue,js,ts,jsx,tsx}",
    // 如果有独立的工具函数生成类名,也要包含
    "./src/utils/classNames.ts",
  ],
}

注意事项:

  • 不要在代码中动态拼接类名(Tailwind 通过字符串匹配扫描,动态拼接会被删除)
  • 动态类名必须完整写出:
// 错误:Tailwind 扫描不到 bg-blue-500、bg-red-500
const color = 'blue'
const className = `bg-${color}-500`

// 正确:完整的类名字符串
const classMap = {
  blue: 'bg-blue-500',
  red:  'bg-red-500',
  green: 'bg-green-500',
}
const className = classMap[color]
  • 如果使用了第三方组件库,将其路径也加入 content 扫描

clsx 和 tailwind-merge 工具

npm install clsx tailwind-merge
// utils/cn.ts
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'

// cn 函数:合并类名,自动解决 Tailwind 类冲突
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}
<script setup>
import { cn } from '@/utils/cn'

// twMerge 会正确处理 Tailwind 类冲突
// 例如 'px-2 px-4' 会合并为 'px-4'(后者优先)
const classes = cn(
  'px-4 py-2 rounded-lg',         // 基础类
  props.variant === 'primary' && 'bg-blue-500 text-white',
  props.disabled && 'opacity-50',
  props.className,                  // 外部传入的类(可覆盖内部类)
)
</script>

clsx 解决条件类名的可读性问题,tailwind-merge 解决 Tailwind 类名冲突(如同时有 px-2px-4 时自动保留后者)。


100 个常用工具类速查表

布局类

类名 CSS 等价 用途
container max-width + 断点适配 内容区域容器
flex display: flex 弹性布局
grid display: grid 网格布局
hidden display: none 隐藏元素
block display: block 块级显示
inline-flex display: inline-flex 行内弹性布局
relative position: relative 相对定位
absolute position: absolute 绝对定位
fixed position: fixed 固定定位
sticky position: sticky 粘性定位
inset-0 top/right/bottom/left: 0 覆盖父元素
overflow-hidden overflow: hidden 裁剪溢出内容
overflow-auto overflow: auto 按需滚动
z-10 z-index: 10 层级
truncate 单行溢出省略 文字截断

Flexbox 类

类名 CSS 等价 用途
flex-col flex-direction: column 垂直排列
flex-row flex-direction: row 水平排列
flex-wrap flex-wrap: wrap 允许换行
items-center align-items: center 交叉轴居中
items-start align-items: flex-start 交叉轴顶对齐
items-end align-items: flex-end 交叉轴底对齐
justify-center justify-content: center 主轴居中
justify-between justify-content: space-between 两端对齐
justify-end justify-content: flex-end 主轴末端
flex-1 flex: 1 1 0% 均分剩余空间
shrink-0 flex-shrink: 0 禁止压缩
gap-4 gap: 1rem 子元素间距
gap-2 gap: 0.5rem 小间距
gap-6 gap: 1.5rem 中等间距
gap-8 gap: 2rem 大间距

Grid 类

类名 CSS 等价 用途
grid-cols-2 repeat(2, 1fr) 两列网格
grid-cols-3 repeat(3, 1fr) 三列网格
grid-cols-4 repeat(4, 1fr) 四列网格
grid-cols-12 repeat(12, 1fr) 十二列栅格
col-span-2 span 2 跨越两列
col-span-full 1 / -1 跨越所有列

Spacing 类

类名 CSS 等价 用途
p-4 padding: 1rem 四边内边距
px-4 padding-left/right: 1rem 水平内边距
py-4 padding-top/bottom: 1rem 垂直内边距
pt-4 padding-top: 1rem 上内边距
pb-4 padding-bottom: 1rem 下内边距
m-4 margin: 1rem 四边外边距
mx-auto margin-left/right: auto 水平居中
mt-4 margin-top: 1rem 上外边距
mb-4 margin-bottom: 1rem 下外边距
space-y-4 子元素垂直间距 1rem 垂直间距(不含 gap)

Sizing 类

类名 CSS 等价 用途
w-full width: 100% 全宽
w-auto width: auto 自动宽度
w-screen width: 100vw 视口宽度
h-full height: 100% 全高
h-screen height: 100vh 视口高度
min-h-screen min-height: 100vh 最小视口高度
max-w-7xl max-width: 80rem 最大宽度限制
max-w-lg max-width: 32rem 表单常用最大宽度

Typography 类

类名 CSS 等价 用途
text-sm font-size: 0.875rem 小字体
text-base font-size: 1rem 正文字体
text-lg font-size: 1.125rem 略大字体
text-xl font-size: 1.25rem 副标题
text-2xl font-size: 1.5rem 标题
text-3xl font-size: 1.875rem 大标题
font-normal font-weight: 400 正常字重
font-medium font-weight: 500 中等字重
font-semibold font-weight: 600 半粗
font-bold font-weight: 700 粗体
text-center text-align: center 居中
text-left text-align: left 左对齐
leading-relaxed line-height: 1.625 宽松行高
tracking-wide letter-spacing: 0.025em 宽字距
uppercase text-transform: uppercase 大写

颜色类

类名 用途
text-gray-500 辅助文字
text-gray-900 主要文字
text-white 白色文字(用于深色背景)
text-blue-600 链接/主色文字
bg-white 白色背景
bg-gray-50 浅灰背景
bg-gray-100 次级背景
bg-blue-600 主色背景

Border 类

类名 CSS 等价 用途
border border-width: 1px solid 默认边框
border-gray-200 边框颜色 浅灰边框
border-gray-300 边框颜色 中灰边框
rounded border-radius: 0.25rem 小圆角
rounded-lg border-radius: 0.5rem 中圆角
rounded-xl border-radius: 0.75rem 大圆角
rounded-2xl border-radius: 1rem 更大圆角
rounded-full border-radius: 9999px 圆形
divide-y 子元素间水平分割线 列表分割
divide-gray-200 分割线颜色 浅灰分割线

Effects 类

类名 CSS 等价 用途
shadow 基础阴影 卡片阴影
shadow-md 中阴影 浮层阴影
shadow-lg 大阴影 弹窗阴影
ring-2 2px 轮廓 焦点样式
ring-blue-500 蓝色轮廓 主色焦点
opacity-50 opacity: 0.5 禁用态

Transition 类

类名 CSS 等价 用途
transition 常用属性过渡 通用过渡
transition-colors 颜色过渡 hover 颜色变化
transition-transform 变换过渡 缩放/移动动画
duration-200 200ms 时长 快速交互
duration-300 300ms 时长 标准过渡
ease-in-out 缓入缓出 通用缓动
hover:scale-105 悬停放大 5% 卡片悬停效果

综合实战示例

响应式导航栏

<!-- 导航栏:移动端汉堡菜单 + 桌面端横排链接 -->
<nav class="bg-white border-b border-gray-200 sticky top-0 z-50">
  <div class="container mx-auto px-4">
    <div class="flex items-center justify-between h-16">

      <!-- Logo 区域 -->
      <div class="flex items-center gap-2">
        <div class="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center">
          <span class="text-white font-bold text-sm">T</span>
        </div>
        <span class="font-bold text-gray-900 text-lg">品牌名称</span>
      </div>

      <!-- 桌面端导航链接(移动端隐藏) -->
      <div class="hidden md:flex items-center gap-1">
        <a href="#" class="text-gray-600 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-sm font-medium transition-colors">
          首页
        </a>
        <a href="#" class="text-gray-600 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-sm font-medium transition-colors">
          产品
        </a>
        <a href="#" class="text-gray-600 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-sm font-medium transition-colors">
          文档
        </a>
        <a href="#" class="text-gray-600 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-sm font-medium transition-colors">
          关于
        </a>
      </div>

      <!-- 右侧操作按钮 -->
      <div class="flex items-center gap-3">
        <button class="hidden md:inline-flex items-center px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-100 rounded-md transition-colors">
          登录
        </button>
        <button class="inline-flex items-center px-4 py-1.5 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-lg transition-colors">
          注册
        </button>
        <!-- 移动端汉堡菜单按钮 -->
        <button class="md:hidden p-2 text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-md transition-colors">
          <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
          </svg>
        </button>
      </div>
    </div>
  </div>
</nav>

响应式卡片列表

<!-- 卡片网格:移动端单列,平板两列,桌面三列 -->
<section class="py-12 bg-gray-50">
  <div class="container mx-auto px-4">

    <!-- 标题区域 -->
    <div class="text-center mb-10">
      <h2 class="text-3xl font-bold text-gray-900 mb-3">精选内容</h2>
      <p class="text-gray-500 max-w-xl mx-auto text-lg">
        浏览我们精心筛选的内容,发现更多可能
      </p>
    </div>

    <!-- 卡片网格 -->
    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">

      <!-- 单个卡片 -->
      <div class="group bg-white rounded-2xl overflow-hidden shadow hover:shadow-lg transition-shadow duration-300 cursor-pointer">

        <!-- 卡片封面图(使用渐变色代替实际图片) -->
        <div class="h-48 bg-gradient-to-br from-blue-400 to-indigo-600 relative overflow-hidden">
          <!-- 标签 -->
          <div class="absolute top-3 left-3">
            <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-white/20 text-white backdrop-blur-sm">
              技术
            </span>
          </div>
          <!-- 悬停时显示的叠加层 -->
          <div class="absolute inset-0 bg-black/20 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
            <span class="text-white font-medium text-sm">查看详情</span>
          </div>
        </div>

        <!-- 卡片内容 -->
        <div class="p-5">
          <!-- 元信息 -->
          <div class="flex items-center gap-2 text-xs text-gray-400 mb-3">
            <span>2026-03-05</span>
            <span>·</span>
            <span>5 分钟阅读</span>
          </div>

          <!-- 标题(悬停变色) -->
          <h3 class="font-semibold text-gray-900 text-lg leading-snug mb-2 group-hover:text-blue-600 transition-colors">
            Tailwind CSS 实战技巧:构建现代化 UI 组件
          </h3>

          <!-- 摘要 -->
          <p class="text-gray-500 text-sm leading-relaxed line-clamp-2">
            本文介绍如何使用 Tailwind CSS 工具类快速搭建响应式用户界面,包含常用模式和最佳实践。
          </p>

          <!-- 底部:作者 + 操作 -->
          <div class="flex items-center justify-between mt-4 pt-4 border-t border-gray-100">
            <div class="flex items-center gap-2">
              <div class="w-7 h-7 rounded-full bg-gradient-to-br from-purple-400 to-pink-400 flex items-center justify-center">
                <span class="text-white text-xs font-medium">A</span>
              </div>
              <span class="text-sm text-gray-600">作者名</span>
            </div>
            <button class="text-blue-600 text-sm font-medium hover:text-blue-800 transition-colors">
              阅读 &rarr;
            </button>
          </div>
        </div>
      </div>

      <!-- 可以重复以上卡片结构 -->

    </div>

    <!-- 加载更多按钮 -->
    <div class="text-center mt-10">
      <button class="inline-flex items-center gap-2 px-6 py-3 border border-gray-300 text-gray-700 font-medium rounded-xl hover:bg-gray-50 hover:border-gray-400 transition-colors duration-200">
        加载更多
        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
        </svg>
      </button>
    </div>
  </div>
</section>

Vue3 综合组件示例

<!-- components/FeatureCard.vue:带 hover 效果的功能介绍卡片 -->
<template>
  <div
    class="group relative flex flex-col p-6 bg-white rounded-2xl border border-gray-200 hover:border-blue-300 hover:shadow-lg transition-all duration-300 cursor-pointer"
    :class="{ 'ring-2 ring-blue-500': isSelected }"
    @click="$emit('select', feature.id)"
  >
    <!-- 图标区域 -->
    <div
      class="inline-flex items-center justify-center w-12 h-12 rounded-xl mb-4 transition-colors duration-300"
      :class="iconBgClass"
    >
      <component :is="feature.icon" class="w-6 h-6" :class="iconColorClass" />
    </div>

    <!-- 标题 -->
    <h3 class="text-lg font-semibold text-gray-900 mb-2 group-hover:text-blue-700 transition-colors">
      {{ feature.title }}
    </h3>

    <!-- 描述 -->
    <p class="text-gray-500 text-sm leading-relaxed flex-1">
      {{ feature.description }}
    </p>

    <!-- 底部:了解更多链接 -->
    <div class="flex items-center gap-1 mt-4 text-sm font-medium text-blue-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
      <span>了解更多</span>
      <svg class="w-4 h-4 transform group-hover:translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
      </svg>
    </div>

    <!-- 选中状态标记 -->
    <div
      v-if="isSelected"
      class="absolute top-3 right-3 w-5 h-5 bg-blue-500 rounded-full flex items-center justify-center"
    >
      <svg class="w-3 h-3 text-white" fill="currentColor" viewBox="0 0 20 20">
        <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
      </svg>
    </div>
  </div>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  feature: {
    type: Object,
    required: true,
    // 期望结构:{ id, title, description, icon, color }
  },
  isSelected: {
    type: Boolean,
    default: false,
  },
})

defineEmits(['select'])

// 根据传入的 color 属性动态生成 Tailwind 类
// 注意:必须写完整的类名字符串,不能动态拼接(如 `bg-${color}-100` 会被 PurgeCSS 删除)
const colorMap = {
  blue:   { bg: 'bg-blue-100',   icon: 'text-blue-600' },
  green:  { bg: 'bg-green-100',  icon: 'text-green-600' },
  purple: { bg: 'bg-purple-100', icon: 'text-purple-600' },
  orange: { bg: 'bg-orange-100', icon: 'text-orange-600' },
  red:    { bg: 'bg-red-100',    icon: 'text-red-600' },
}

const iconBgClass = computed(() => colorMap[props.feature.color]?.bg ?? 'bg-gray-100')
const iconColorClass = computed(() => colorMap[props.feature.color]?.icon ?? 'text-gray-600')
</script>
<!-- 父组件:功能网格展示 -->
<template>
  <section class="py-16">
    <div class="container mx-auto px-4 max-w-6xl">
      <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5">
        <FeatureCard
          v-for="feature in features"
          :key="feature.id"
          :feature="feature"
          :is-selected="selectedId === feature.id"
          @select="selectedId = $event"
        />
      </div>
    </div>
  </section>
</template>

<script setup>
import { ref } from 'vue'
import FeatureCard from './FeatureCard.vue'

const selectedId = ref(null)

const features = [
  { id: 1, title: '快速开发', description: '工具类直接写在 HTML,无需在文件间来回切换。', color: 'blue' },
  { id: 2, title: '高度定制', description: '通过配置文件轻松扩展设计系统,保持全局一致性。', color: 'purple' },
  { id: 3, title: '生产就绪', description: 'PurgeCSS 自动移除未使用样式,包体积极小。', color: 'green' },
]
</script>

踩坑与注意事项

动态类名必须完整书写

Tailwind 通过静态分析扫描文件中的完整类名字符串。任何动态拼接都会导致生产构建中类名被删除。

// 错误:构建后 bg-blue-500 会消失
const color = 'blue'
el.className = `bg-${color}-500`

// 正确:完整写出所有可能的类名
const colorClasses = { blue: 'bg-blue-500', red: 'bg-red-500' }
el.className = colorClasses[color]

不要在 style 属性中使用 @apply

@apply 只能在 CSS 文件(.css/.scss/.vue 的 <style> 块)中使用,不能在行内 style 属性中使用。

优先级问题

Tailwind 工具类都在同一层级,如果两个类作用于同一属性,以 HTML 中最后声明的类为准(CSS 权重相同时,后定义的样式生效)。使用 tailwind-merge 可以避免此类冲突。

JIT 模式(Tailwind v3 默认开启)

Tailwind v3 默认使用 JIT(即时编译)模式,按需生成类,支持任意值语法(如 w-[200px])。不需要手动开启。

不要忘记 content 配置

如果新增了文件类型或目录,必须在 tailwind.config.jscontent 中添加,否则其中使用的工具类会被清除。

与 CSS 模块的兼容性

在使用 CSS Modules 的项目中,如果需要同时使用 Tailwind,确保 Tailwind 的 CSS 文件在全局引入(不通过 CSS Modules 导入),避免类名作用域冲突。


最佳实践

正确配置 content 路径,确保生产包不遗漏类名:Tailwind 通过扫描源文件中的类名字符串来生成 CSS,任何未被 content 覆盖的文件中的类都会被清除。新增文件类型或目录后必须同步更新配置。

// tailwind.config.js
module.exports = {
  content: [
    './src/**/*.{html,js,ts,jsx,tsx,vue}',
    './components/**/*.{js,ts,jsx,tsx}',
  ],
}

@layer components 提取重复样式,而非大量使用 @apply:对于跨多个组件重复的样式组合,定义在 @layer components 中,并赋予语义化类名。@apply 适合少量提取,大量使用会抵消 Tailwind 的维护优势。

@layer components {
  .btn-primary {
    @apply px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors;
  }
  .card {
    @apply rounded-lg border border-gray-200 shadow-sm p-4;
  }
}

使用 tailwind-merge 解决动态类名冲突:在组件接收外部 className 时,直接字符串拼接可能导致同属性两个类并存(后者不一定覆盖前者)。tailwind-merge 会智能去重。

import { twMerge } from 'tailwind-merge'

function Button({ className, ...props }) {
  return (
    <button
      className={twMerge('px-4 py-2 bg-blue-500 text-white', className)}
      {...props}
    />
  )
}

// 调用时传入 bg-red-500,正确覆盖默认颜色
<Button className="bg-red-500" />

优先使用语义化任意值,避免魔法数字散布各处:Tailwind 的任意值语法(w-[200px])适合一次性特殊值,但若同一值在多处重复出现,应通过 theme.extend 定义为设计令牌。

// 将项目特有的间距/颜色加入主题
module.exports = {
  theme: {
    extend: {
      colors: { brand: '#1a73e8' },
      spacing: { sidebar: '240px' },
    },
  },
}

暗色模式用 class 策略,由 JS 控制切换media 策略跟随系统,无法让用户手动切换。class 策略在 <html> 上添加/移除 dark 类,可实现用户偏好记忆。

// tailwind.config.js
module.exports = { darkMode: 'class' }

// 切换暗色模式
document.documentElement.classList.toggle('dark')

常见陷阱

陷阱:动态拼接类名被 Purge 清除

现象: 开发环境样式正常,生产构建后动态计算的类(如 text-${color}-500)不生效,元素无样式。

原因: Tailwind 通过静态扫描源码字符串收集类名,无法识别运行时拼接的字符串片段,导致这些类被 purge 排除出最终 CSS。

解决: 始终写完整类名,不要拆分。如需动态,用对象映射完整类名。

// 错误:拼接,会被 purge
const cls = `text-${color}-500`

// 正确:完整类名映射
const colorMap = {
  red: 'text-red-500',
  blue: 'text-blue-500',
}
const cls = colorMap[color]

陷阱:@apply 在 Scoped CSS / CSS Modules 中失效

现象: 在 Vue <style scoped> 或 CSS Modules 文件中使用 @apply 报错,或样式无效。

原因: @apply 依赖 PostCSS 的 Tailwind 插件处理,但 Scoped CSS 的 scope 属性会干扰生成的选择器,部分构建工具版本下存在兼容性问题。

解决: 将共享样式移到全局 CSS 文件(非 scoped/module)中定义 @layer components,或直接在模板中写工具类。

陷阱:响应式前缀方向理解错误

现象: 设置 md:hidden 期望在小屏隐藏,实际在大屏上才隐藏;布局在小屏上崩掉。

原因: Tailwind 的响应式前缀是移动优先的"最小宽度"断点,md:hidden 表示"在 md 及以上宽度隐藏",不是"在 md 以下隐藏"。

解决: 移动端样式写在无前缀的基础类上,大屏覆写用断点前缀。

<!-- 移动端显示,md 及以上隐藏 -->
<div class="block md:hidden">移动菜单</div>

<!-- 移动端隐藏,md 及以上显示 -->
<div class="hidden md:block">桌面导航</div>

参见

阅读更多

Web 安全基础

1. HTML 转义(服务端渲染必须): 2. CSP(Content Security Policy): 3. HttpOnly Cookie:防止 JS 读取会话 Cookie: 4. 前端框架防护: 攻击者在第三方网站构造一个表单,诱导已登录用户提交,浏览器会自动携带目标站的 Cookie。 触发条件: 1. 用户已登录目标网站(Cookie 有效) 2. 目标 API 仅凭 Cookie 识别用户身份 3. 请求来源未验证 1. CSRF Token(推荐): 2. SameSite Cookie: 3. 验证 Origin/Referer 头:

By yellowdog

HTTP 协议深度指南

HTTP(HyperText Transfer Protocol)是 Web 的基础传输协议,基于 TCP/IP,采用请求/响应模型。 相关文档:Web安全基础(/web-an-quan-ji-chu/) FastAPI完全指南(/fastapi-wan-quan-zhi-nan/) Nginx完全指南(/nginx-wan-quan-zhi-nan/) 幂等性:多次执行相同请求,服务器状态结果相同。PUT /users/1 多次执行结果一致;POST /users 每次创建新资源,非幂等。 浏览器直接从本地缓存读取,不向服务器发送请求。 缓存命中时,状

By yellowdog

系统设计基础

SLA 对照表: 选择建议:无状态服务(Web 层、API 层)优先水平扩展;数据库初期垂直扩展,达到瓶颈后考虑分库分表或读写分离。 缓存穿透(查询不存在的 key,每次都打到 DB): 缓存击穿(热点 key 过期,瞬间大量请求打到 DB): 缓存雪崩(大量 key 同时过期,或缓存服务宕机): 令牌桶 Python 实现: Redis 实现分布式限流(滑动窗口): URL 命名规则: Cursor 分页响应格式: 雪花算法结构(64 bit): 定义:分布式系统不能同时满足以下三个特性: 在分布式环境中 P 是必须保证的,所以实际是 CP vs AP

By yellowdog

算法思路与模板

二分查找要求序列有序,每次将搜索范围缩减一半,时间复杂度 O(log n)。 两个指针从两端向中间收缩,常用于有序数组。 滑动窗口维护一个满足条件的区间 left, right,right 不断向右扩张,条件不满足时收缩 left。 滑动窗口通用框架: 1. 确定"子问题":原问题可以分解为哪些规模更小的同类问题 2. 定义 dpi 或 dpij 的含义,要足够清晰 3. 推导状态转移方程 4. 确定初始状态(边界条件) 5. 确定计算顺序(确保依赖的子问题先计算) 每件物品最多选一次。dpj = 容量为 j 时的最大价值,逆序遍历容量防止重复选取。 每

By yellowdog