Skip to content
第 157 / 250 章前端⏱ 10 分钟阅读

第 157 章:Tailwind CSS 样式

学习目标

  • 掌握 Tailwind 原子化类名
  • 学会响应式与暗色模式
  • 理解自定义配置
  • 用 cn() 合并类名

一、Tailwind 是什么

Utility-First CSS 框架,直接在 JSX 中写类名,无需写 CSS 文件。

tsx
<button className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">
  点击
</button>

二、安装

Next.js 创建时已选 Tailwind,手动安装:

bash
pnpm add -D tailwindcss postcss autoprefixer
pnpm dlx tailwindcss init -p

三、配置

3.1 tailwind.config.ts

ts
import type { Config } from 'tailwindcss';

const config: Config = {
  content: [
    './app/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {
      colors: {
        brand: '#42b883',
      },
    },
  },
  plugins: [],
};

export default config;

3.2 globals.css

css
@tailwind base;
@tailwind components;
@tailwind utilities;

四、常用类名

4.1 布局

类名作用
flexflex 布局
gridgrid 布局
block inline-block显示
hidden隐藏
mx-auto水平居中
container容器

4.2 间距

类名含义
p-4padding 1rem
px-4左右 padding
py-2上下 padding
m-4margin 1rem
mt-2 mb-4单边
space-y-2子元素垂直间距

4.3 尺寸

类名含义
w-full宽度 100%
w-1/250%
w-328rem
h-screen视口高度
min-h-screen最小视口高度
max-w-md最大宽度

4.4 颜色

类名含义
bg-blue-500背景蓝
text-white文字白
border-gray-200边框灰
text-red-500/50红色 50% 透明

色阶:50 / 100 / 200 / ... / 900 / 950

4.5 排版

类名含义
text-sm text-lg text-xl字号
font-bold font-medium字重
text-center text-left对齐
leading-relaxed行高
truncate截断...

4.6 圆角与阴影

类名含义
rounded rounded-lg rounded-full圆角
shadow shadow-md shadow-lg阴影

五、伪类与状态

tsx
<button className="
  bg-blue-500             // 默认
  hover:bg-blue-600       // 悬停
  active:bg-blue-700      // 按下
  focus:outline-none      // 聚焦
  focus:ring-2            // 聚焦环
  disabled:opacity-50     // 禁用
  disabled:cursor-not-allowed
">
  提交
</button>

六、响应式

前缀宽度
sm:≥640px
md:≥768px
lg:≥1024px
xl:≥1280px
2xl:≥1536px
tsx
<div className="
  flex flex-col        // 默认:手机端纵向
  md:flex-row          // 平板及以上:横向
  lg:gap-8             // 桌面端间距加大
">
  <div>左侧</div>
  <div>右侧</div>
</div>

七、暗色模式

tsx
<div className="
  bg-white
  text-black
  dark:bg-gray-900
  dark:text-white
">
  内容
</div>

八、cn() 合并类名

clsx + tailwind-merge:

bash
pnpm add clsx tailwind-merge
tsx
// lib/utils.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
tsx
// 使用
import { cn } from '@/lib/utils';

function Button({ variant, className, ...rest }: ButtonProps) {
  return (
    <button
      className={cn(
        'px-4 py-2 rounded',
        variant === 'primary' && 'bg-blue-500 text-white',
        variant === 'danger' && 'bg-red-500 text-white',
        className  // 外部传入可覆盖
      )}
      {...rest}
    />
  );
}

九、自定义组件

tsx
// components/Card.tsx
import { cn } from '@/lib/utils';

export function Card({ className, children }: { className?: string; children: React.ReactNode }) {
  return (
    <div className={cn('rounded-lg border p-4 shadow-sm', className)}>
      {children}
    </div>
  );
}

十、条件类名

tsx
import { cn } from '@/lib/utils';

function NavLink({ active }: { active: boolean }) {
  return (
    <a
      className={cn(
        'px-3 py-2 rounded',
        active
          ? 'bg-blue-500 text-white'
          : 'text-gray-700 hover:bg-gray-100'
      )}
    >
      链接
    </a>
  );
}

十一、Tailwind vs CSS-in-JS

维度TailwindCSS-in-JS (styled)
学习记类名写 CSS
性能极快(零运行时)有运行时开销
动态需 cn()直接 props
维护类名多组件化
适合通用项目设计系统

十二、本章小结

概念关键
Utility-First直接用类名,无 CSS
响应式md: lg: 前缀
暗色dark: 前缀
状态hover: focus:
cn()合并类名,处理冲突
自定义tailwind.config extend

动手练习

  1. 用 Tailwind 实现一个卡片组件
  2. 实现响应式导航栏(手机端汉堡菜单)
  3. 实现暗色模式切换
  4. 用 cn() 封装一个 Button 组件(3 个 variant)

推荐阅读


下一章:第 158 章:Next.js App Router 深入

本站基于 VitePress 构建 · 由 Codebook 团队维护