TailwindCSS 如何实现复杂布局?Flex、Grid 与响应式怎么选?
TailwindCSS 做复杂布局,关键不是背更多 class,而是先判断页面属于哪类布局:一维排布用 Flex,二维排布用 Grid,需要脱离文档流时再用定位。很多布局写乱,往往不是 TailwindCSS 的问题,而是一开始就把工具选错了。
比如导航栏、按钮组、表单行,更适合 Flex;商品卡片墙、仪表盘、圣杯布局,更适合 Grid;浮动徽标、固定底栏、吸顶标题,则交给 relative、absolute、fixed、sticky。
先判断:Flex 还是 Grid?
一句话判断:Flex 解决一条轴上的排列,Grid 解决行和列同时存在的布局。
如果只关心元素横着排还是竖着排,比如头像加用户名、按钮靠右、导航菜单换行,用 Flex 更自然:
html<div class="flex items-center justify-between gap-4"> <div class="flex items-center gap-2"> <img class="h-10 w-10 rounded-full" src="/avatar.png" alt="用户头像" /> <span>Leven</span> </div> <button class="rounded bg-blue-600 px-4 py-2 text-white">关注</button> </div>
如果需要同时控制列宽、行距、跨列、响应式列数,用 Grid 会更清楚:
html<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4"> <article class="rounded-lg border p-4">卡片 1</article> <article class="rounded-lg border p-4">卡片 2</article> </div>
Flex:处理导航、工具栏和局部对齐
Flex 的核心是主轴和交叉轴。常用类包括 flex-row、flex-col、flex-wrap、justify-*、items-*、flex-1、shrink-0、basis-*。
html<header class="flex flex-wrap items-center justify-between gap-4 border-b px-4 py-3"> <a class="shrink-0 text-lg font-semibold" href="/">Logo</a> <nav class="flex flex-wrap items-center gap-3 text-sm"> <a href="/docs">文档</a> <a href="/pricing">价格</a> </nav> <div class="flex items-center gap-2"> <button class="rounded px-3 py-1.5">登录</button> <button class="rounded bg-black px-3 py-1.5 text-white">注册</button> </div> </header>
flex-wrap 能让导航在小屏幕上自然换行;shrink-0 适合 Logo、头像、图标按钮这类不希望被压缩的元素。
Grid:处理二维布局、响应式列和跨列
html<section class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3"> <article class="rounded-xl border p-5">文章卡片</article> <article class="rounded-xl border p-5">文章卡片</article> </section>
需要某个卡片跨列时,用 col-span-*:
html<section class="grid grid-cols-1 gap-4 md:grid-cols-4"> <article class="rounded-xl border p-5 md:col-span-2">重点内容</article> <article class="rounded-xl border p-5">普通内容</article> </section>
移动端优先:grid-cols-1 是小屏默认值,sm:、lg: 逐步增强。
用 minmax 和 auto-fit 写更耐用的卡片网格
如果卡片数量不固定,可以用任意值语法写 repeat(auto-fit,minmax()):
html<section class="grid grid-cols-[repeat(auto-fit,minmax(240px,1fr))] gap-4"> <article class="rounded-xl border p-5">卡片</article> <article class="rounded-xl border p-5">卡片</article> </section>
每张卡片最小 240px,空间够就自动多排几列,不够就换行。相比手动写多个断点,它更适合商品列表、文章列表、工具卡片。
固定侧边栏加自适应内容可以这样写:
html<div class="grid grid-cols-[220px_minmax(0,1fr)] gap-6"> <aside class="rounded border p-4">侧边栏</aside> <main class="min-w-0 rounded border p-4">主内容</main> </div>
Subgrid 和 Container Queries
复杂页面里,如果内层内容想跟父级网格列线对齐,可以用 grid-cols-subgrid:
html<section class="grid grid-cols-4 gap-4"> <article class="col-span-4 grid grid-cols-subgrid rounded-xl border p-4"> <h2 class="col-span-4 text-lg font-semibold md:col-span-1">标题</h2> <p class="col-span-4 md:col-span-3">内容跟随父级网格对齐。</p> </article> </section>
TailwindCSS v4 还可以使用容器查询。父级声明为容器,子元素根据容器宽度变化:
html<article class="@container rounded-xl border p-4"> <div class="grid gap-4 @md:grid-cols-[160px_1fr]"> <img class="aspect-video w-full rounded-lg object-cover" src="/cover.jpg" alt="文章封面" /> <div> <h2 class="font-semibold">TailwindCSS 布局示例</h2> <p class="mt-2 text-sm text-gray-600">容器够宽时左右排,不够宽时上下排。</p> </div> </div> </article>
这种写法更适合组件库和模块化页面。组件不再只看屏幕宽度,而是根据实际容器空间调整布局。
定位和居中
Flex 和 Grid 负责正常布局流,定位负责特殊位置。徽标、角标适合 relative + absolute:
html<div class="relative inline-block"> <button class="rounded-lg border px-4 py-2">消息</button> <span class="absolute -right-2 -top-2 rounded-full bg-red-500 px-1.5 text-xs text-white">3</span> </div>
固定底部操作栏用 fixed,文章目录和筛选栏常用 sticky。注意 sticky 会受父元素 overflow 影响。
居中也不用猜:块级容器水平居中用 mx-auto max-w-*;水平垂直居中可以用 Flex,也可以用 grid place-items-center。
圣杯布局和卡片网格
html<body class="min-h-screen bg-gray-50"> <div class="grid min-h-screen grid-rows-[auto_1fr_auto]"> <header class="border-b bg-white px-4 py-3">Header</header> <div class="grid grid-cols-1 md:grid-cols-[240px_minmax(0,1fr)]"> <aside class="border-r bg-white p-4">Sidebar</aside> <main class="min-w-0 p-4">Main Content</main> </div> <footer class="border-t bg-white px-4 py-3">Footer</footer> </div> </body>
卡片网格可以外层 Grid 管列数,内层 Flex 让按钮贴底:
html<section class="grid grid-cols-[repeat(auto-fit,minmax(260px,1fr))] gap-5"> <article class="flex flex-col overflow-hidden rounded-xl border bg-white"> <img class="aspect-video w-full object-cover" src="/cover.jpg" alt="封面" /> <div class="flex flex-1 flex-col p-5"> <h2 class="text-lg font-semibold">卡片标题</h2> <p class="mt-2 flex-1 text-sm text-gray-600">这里是卡片描述,长度可以不同。</p> <a class="mt-4 inline-flex items-center text-sm font-medium text-blue-600" href="/detail">查看详情</a> </div> </article> </section>
实用建议
写 TailwindCSS 复杂布局时,可以按这个顺序处理:先确定内容语义,用 header、main、section、article、aside、footer 搭骨架;判断主布局用 Grid 还是 Flex;从移动端开始写默认样式,再用断点增强;特殊悬浮、角标、吸顶再使用定位;遇到组件在不同容器里表现不同,考虑 @container;能少嵌套就少嵌套,结构清楚比 class 看起来短更重要。
TailwindCSS 的布局能力本质上还是 CSS,只是换成了工具类表达。复杂页面真正难的不是某个 class 怎么写,而是先把布局关系想清楚:谁负责行列,谁负责对齐,谁需要脱离文档流,谁应该随容器变化。