news 2026/9/10 2:00:52

Tailwind CSS Grid 响应式布局实战:从 3 列基础栅格到 16 列自定义扩展(refine 项目实践)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Tailwind CSS Grid 响应式布局实战:从 3 列基础栅格到 16 列自定义扩展(refine 项目实践)

Tailwind CSS Grid 响应式布局实战:从 3 列基础栅格到 16 列自定义扩展(refine 项目实践)

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

导读:本文以 Tailwind CSS 的 Grid 工具类为核心,从 Block Formatting Context(BFC)出发,逐步引入gridgrid-cols-{n}gap-{size}col-span-{n}grid-rows-{n}等类,最终实现一个包含导航栏、侧栏、主内容区和页脚的响应式页面骨架。读完本文,你将掌握 Tailwind Grid 的完整用法(含移动优先断点语义、跨列跨行、断点重排),并能在tailwind.config.js中把默认 12 列栅格扩展为 16 列。文章同时结合 refine 仓库中真实示例(examples/store、examples/blog-refine-daisyui、examples/blog-refine-shadcn)给出可复制的实战佐证。

Tailwind 的 Grid 系统:为什么不用 Flexbox 切分宽度

Tailwind CSS(简称 Tailwind)是一个用于快速构建网站的 CSS 框架,内置了一批开箱即用的工具类(utility classes),可以按需组合,并能在后续通过配置文件轻易定制,以适配任意设计在响应式、布局与主题上的需求。

在 Tailwind 1.2 之前的版本里,构建多列布局通常依赖 Flexbox 工具类,用w-{fraction}(如w-1/3)手工把容器的宽度切分成若干列。而从 1.2 版本起,Tailwind 提供了一整套基于原生 CSS Grid 的类,可以构建更精细的多行多列布局。

与 Twitter Bootstrap、Foundation 这类底层仍用 Flexbox 实现 12 列栅格的框架不同,Tailwind 直接使用 CSS Grid,让我们可以构建任意列数与行数、高度可定制的布局。它提供的 Grid 容器类包括:

  • grid:启用 Grid Formatting Context
  • grid-cols-{n}:定义列数
  • grid-rows-{n}:定义行数

以及用于控制 Grid 子元素行为的类,例如col-span-{n}row-span-{n}col-start-{n}col-end-{n}row-start-{n}row-end-{n}等。

Tailwind 默认配置最多支持单屏 12 列,可以通过tailwind.config.js自定义;与 Grid 相关的许多选项都可以按需调整。本文后面会演示如何把列数上限扩展到 16。

建议进一步查阅 Tailwind CSS 官方文档中 grid-template-columns 及其后续的 grid-column-start / grid-column-end / grid-template-rows 等章节,作为工具类的完整参考。

项目目标:一个 3 列 5 行的页面骨架

我们从一个最简单的 HTML 文档开始,逐步实现如下目标布局:

  • 顶部导航栏(navbar)
  • 左侧内容区(side content)
  • 主内容区(main content)
  • 底部页脚(footer)

这个布局由 3 列、5 行组成。我们会先用一组遵循 Block Formatting Context(BFC)的div起步,再按需引入 Grid 相关类,逐步过渡到 Grid Formatting Context(GFC),在过程中理解每一类的作用。

项目初始化与开发环境准备

动手前先准备好环境:

  1. 克隆配套的演示仓库(包含上述目标布局的起步代码),在代码编辑器中打开。
  2. 确保编辑器安装了 Live Server 插件并处于启用状态。
  3. 安装依赖并编译样式,使用 Tailwind CLI 监视模式:
npx tailwindcss -i ./src/styles.css -o ./dist/styles.css --watch
  1. 启动 Live Server,点击编辑器右下角的Go Live按钮,或在浏览器中直接访问 Live Server 提供的端口号。

index.html通过<link>引入编译产物/dist/styles.css,改动源码后 Tailwind 会在监视模式下自动重新生成样式。

基础示例:一个 9 宫格页面

先看起步用的index.html,它由 9 个不同背景色的tile组成,目前只是普通块级元素(BFC),从上到下依次堆叠:

<!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link href="/dist/styles.css" rel="stylesheet" /> <title>Document</title> </head> <body> <div class="container m-auto"> <div class="tile bg-teal-500"> <h1 class="tile-marker">ONE</h1> </div> <div class="tile bg-amber-500"> <h1 class="tile-marker">TWO</h1> </div> <div class="tile bg-yellow-500"> <h1 class="tile-marker">THREE</h1> </div> <div class="tile bg-lime-600"> <h1 class="tile-marker">FOUR</h1> </div> <div class="tile bg-green-600"> <h1 class="tile-marker">FIVE</h1> </div> <div class="tile bg-emerald-500"> <h1 class="tile-marker">SIX</h1> </div> <div class="tile bg-teal-500"> <h1 class="tile-marker">SEVEN</h1> </div> <div class="tile bg-purple-500"> <h1 class="tile-marker">EIGHT</h1> </div> <div class="tile bg-pink-500"> <h1 class="tile-marker">NINE</h1> </div> </div> </body> </html>

建立 Grid Formatting Context

grid类:看似什么都不发生

给容器加上grid类:

<div class="container m-auto grid"></div>

此时页面看不出任何变化——因为默认的grid只有一列,子元素仍然按一列堆叠。但布局上下文已经从 BFC 切换为 Grid Formatting Context(GFC)。

grid-cols-{n}:显式声明列数

添加三列:

<div class="container m-auto grid grid-cols-3"></div>

现在 9 个div按 Grid Formatting Context 流入了 3 列。

需要注意的是,grid-cols-3并不是简单地“把屏幕切成 3 等份”,其底层 CSS 等价于:

grid-template-columns: repeat(3, minmax(0, 1fr));

即每列都是1fr弹性轨道,且用minmax(0, 1fr)防止内容的最小内容尺寸(min-content)把轨道撑爆——这是 Tailwind Grid 列宽行为的关键细节,也是它比手动写1fr更稳妥的原因。

gap-{size}:设置栅格间距

间距需要设置在 Grid 容器上,而不是子元素上:

<div class="container m-auto grid grid-cols-3 gap-4"></div>

gap-4会为子元素之间添加统一的间距(同时作用于行与列)。Tailwind 也提供gap-x-{size}gap-y-{size}分别控制水平、垂直方向的间距。

响应式列数:md:lg:前缀

在更大断点下增加列数:

<div class="container m-auto grid grid-cols-3 gap-4 md:grid-cols-5 lg:grid-cols-8" ></div>

这里用到 Tailwind 默认断点体系中的md(768px)和lg(1024px)。观察页面缩放可以看到列数在 768px、1024px 两处递增。

这里有一个非常重要的语义:Tailwind 的响应式前缀(mdlg等)不是“屏幕尺寸”而是移动优先(mobile-first)断点。所以:

  • grid-cols-3对所有屏幕尺寸都生效(3 列是基线);
  • 屏幕宽度超过md(≥768px)后,列数变为 5;
  • 屏幕宽度超过lg(≥1024px)后,列数变为 8;
  • 之后没有再次改变,所以即使到了xl2xl,仍然是 8 列。

这意味着一套类即可覆盖从小屏到大屏的完整响应式曲线,前提是理解“前缀代表 min-width 阈值,而非某个具体设备”。

控制尺寸与位置:span 与 start/end

Grid 的尺寸与放置类给了我们更多控制:某个区块跨几列、从哪一列开始、到哪一列结束。

col-span-{n}设置跨列尺寸

把第一个div当作导航栏,让它从栅格起点开始、在每个屏幕尺寸下都横跨整行:

<div class="tile col-span-3 bg-teal-500 md:col-span-5 lg:col-span-8"> <h1 class="tile-marker">ONE</h1> </div>

注意这里在三个断点分别写col-span-3md:col-span-5lg:col-span-8,恰好等于对应断点下的总列数,即“占满整行”。

当需要“始终占满整行”时,可以简化为col-span-full

<div class="tile col-span-full bg-teal-500"> <h1 class="tile-marker">ONE</h1> </div>

也可以用col-start-{n}col-end-{n}组合达到同样效果:

<div class="tile col-start-1 col-end-4 bg-teal-500 md:col-start-1 md:col-end-6 lg:col-start-1 lg:col-end-9" > <h1 class="tile-marker">ONE</h1> </div>

但请看这里每个断点都要同时写 start 和 end 两组响应式类:

md:col-start-1 md:col-end-6 lg:col-start-1 lg:col-end-9

既不 DRY,也容易出错。col-span-{n}更适合表达“尺寸”,而 start/end 更擅长表达“位置”。

继续设置第二、第三个div的宽度:

<div class="tile col-span-1 bg-amber-500 md:col-span-2 lg:col-span-3"> <h1 class="tile-marker">TWO</h1> </div> <div class="tile col-span-2 bg-yellow-500 md:col-span-3 lg:col-span-5"> <h1 class="tile-marker">THREE</h1> </div>

col-start-{n}放置元素:start 负责位置、span 负责尺寸

单独使用col-span-{n}时,对元素在栅格中的放置自由度有限;而单独使用col-start-{n}/col-end-{n}又会在响应式场景下带来大量重复。最佳实践是组合使用:start 类定位,span 类定宽高

以第四个div为例,让它在lg断点从第 4 列开始、向右跨 2 列:

<div class="tile bg-lime-600 lg:col-span-2 lg:col-start-4"> <h1 class="tile-marker">FOUR</h1> </div>

可以看到,从lg起第四个div从第 4 列开始向右跨两列,代码比“start + end 双写”精简得多。

但此时如果仔细观察整体布局,会发现它仍是一盘散沙:最后两个div游离在整体之外。原因是我们只完成了“一半的方程式”——只用了 Grid 的相关类,还没有显式管理 Grid 的

显式定义行:grid-rows-{n}

要对栅格有更精细的控制,需要像声明列一样显式声明行数。目前行数是隐式(implicit)生成的,现在我们显式声明 5 行:

<div class="container m-auto grid grid-cols-3 grid-rows-5 gap-4 md:grid-cols-5 lg:grid-cols-8" ></div>

grid-rows-5对应grid-template-rows: repeat(5, minmax(0, 1fr)),等价地创建 5 个等高的行轨道。

row-start-{n}把页脚放到最底行

现在把最后一个div设置为页脚:小屏时放到最底行的左侧,md之后横跨整行:

<div class="tile row-start-5 bg-pink-500 md:col-span-full"> <h1 class="tile-marker">NINE</h1> </div>

row-start-5告诉页脚从第 5 行(最底行)开始放置;配合md:col-span-full,页脚在md之后铺满整行。

跨行:row-start-{n}+row-end-{n}

让第二个div占据导航栏与页脚之间的左侧整列——起点选在第 2 行、终点为第 5 行:

<div class="tile col-span-1 row-start-2 row-end-5 bg-amber-500 md:col-span-2 lg:col-span-3" > <h1 class="tile-marker">TWO</h1> </div>

此时页面开始成型:顶部导航、左侧侧栏、右侧内容、底部页脚,一个接近真实网站的布局已经出现。

在不同断点重排区块(Reorder Regions)

改变row-start-{n}/col-start-{n}n的值,就可以在不同断点重新排列区块顺序。

例如把第三个div当作一个广告位:小屏时展示在底部,md之后移到顶部。先设置小屏顺序,再在md覆盖:

<div class="tile col-span-2 row-start-4 row-end-5 bg-yellow-500 md:col-span-3 md:row-start-2 md:row-end-3 lg:col-span-5" > <h1 class="tile-marker">THREE</h1> </div>

在小屏上,它位于第 4 行(接近底部);一旦超过mdmd:row-start-2 md:row-end-3把它提升到第 2 行(靠近顶部),列宽也随之调整为md:col-span-3。这种“同一个 DOM 节点在不同断点出现在不同区域”的能力,是 CSS Grid 相对于传统 float/Flexbox 布局的重要优势,且无需改动 HTML 结构顺序。

完整的最终代码

整合以上所有步骤后,最终的index.html如下:

<!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link href="/dist/styles.css" rel="stylesheet" /> <title>Document</title> </head> <body> <div class="container m-auto grid grid-cols-3 grid-rows-5 gap-4 md:grid-cols-5 lg:grid-cols-8" > <div class="tile col-span-full bg-teal-500"> <h1 class="tile-marker">ONE</h1> </div> <div class="tile col-span-1 row-start-2 row-end-5 bg-amber-500 md:col-span-2 lg:col-span-3" > <h1 class="tile-marker">TWO</h1> </div> <div class="tile col-span-2 row-start-4 row-end-5 bg-yellow-500 md:col-span-3 md:row-start-2 md:row-end-3 lg:col-span-5" > <h1 class="tile-marker">THREE</h1> </div> <div class="tile bg-lime-600 lg:col-span-2 lg:col-start-4"> <h1 class="tile-marker">FOUR</h1> </div> <div class="tile bg-green-600"> <h1 class="tile-marker">FIVE</h1> </div> <div class="tile bg-emerald-500"> <h1 class="tile-marker">SIX</h1> </div> <div class="tile bg-teal-500"> <h1 class="tile-marker">SEVEN</h1> </div> <div class="tile bg-purple-500"> <h1 class="tile-marker">EIGHT</h1> </div> <div class="tile row-start-5 bg-pink-500 md:col-span-full"> <h1 class="tile-marker">NINE</h1> </div> </div> </body> </html>

Tailwind CSS Grid 类速查表

作用示例
grid启用 Grid 布局<div class="grid"></div>
grid-cols-{n}设置列数grid-cols-3
gap-{size}在栅格项之间添加间距gap-4
col-span-{n}让栅格项跨越多列col-span-2
row-start-{n}设置栅格项的起始行row-start-2
grid-rows-{n}设置行数grid-rows-5

在此基础上,还有对称的row-span-{n}row-end-{n}col-start-{n}col-end-{n},以及独立的gap-x-{size}/gap-y-{size},可以按需组合出任意二维栅格结构。

自定义 Tailwind 主题:把列数扩展到 16

Tailwind 的 Grid 相关配置都可以按需修改。假设业务设计需要最多16 列,那么必须能生成从 0 到 16 的所有grid-cols-{n}类,同时还要生成对应的col-start-{n}col-end-{n}类。

tailwind.config.js中通过extend扩展gridTemplateColumnsgridColumnStartgridColumnEnd三个属性即可:

// tailwind.config.js module.exports = { theme: { extend: { gridTemplateColumns: { // Simple 16 column grid "16": "repeat(16, minmax(0, 1fr))", }, gridColumnStart: { "13": "13", "14": "14", "15": "15", "16": "16", "17": "17", }, gridColumnEnd: { "13": "13", "14": "14", "15": "15", "16": "16", "17": "17", }, }, }, };

说明几点:

  • gridTemplateColumns: { "16": ... }生成grid-cols-16类(n从 1 到 12 的类由默认主题提供,extend不会覆盖它们)。
  • 16 列栅格中,元素的起始/结束行号理论上最多到 17(因为列线数量 = 列数 + 1),所以gridColumnStartgridColumnEnd需要补上 13 到 17 的取值。
  • 配置完成后,重新构建样式(npx tailwindcss -i ./src/styles.css -o ./dist/styles.css --watch会自动触发),grid-cols-16col-start-13等类即可直接使用。

这种“扩展生成规则”的思路也适用于其他维度。在 refine 仓库中可以看到大量同类实践:

  • examples/store/tailwind.config.js 通过theme.extend.screens自定义了整套断点(2xsmall: 320pxsmall: 1024pxmedium: 1280pxlarge: 1440pxxlarge: 1680px等),说明断点体系本身也可以按项目需求重定义;
  • examples/blog-refine-shadcn/tailwind.config.js 通过content指定了pages/components/app/src/等目录,Tailwind 只从这些路径扫描类名并生成用到的工具类;
  • examples/blog-refine-daisyui/tailwind.config.js 同样声明了content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],并挂载daisyui插件——这说明 Grid 类与其他工具类遵循同一套 JIT 扫描机制,只有出现在源码里的类才会被编译进产物

refine 仓库中的真实 Grid 用法佐证

本文的布局思路在 refine 仓库的 Tailwind 示例中有大量同款实践,可以作为进阶参考:

电商示例:响应式商品栅格

examples/store/pages/index.tsx 中的商品列表容器就是标准的“移动优先列数递增”写法:

className={clsx( "flex-1", "grid", "grid-cols-1", "md:grid-cols-2", "lg:grid-cols-3", "gap-x-8", "gap-y-16", )}
  • 基线 1 列 →md起 2 列 →lg起 3 列;
  • gap-x-8/gap-y-16分别控制列间距与行间距(比gap-{size}更精细)。

这与本文“grid-cols-{n}定列数 + 断点前缀定切换时机”的方法完全一致,只是把{n}换成了 1/2/3,并叠加了商品卡片组件。

账号概览:@apply组合 Grid 类

examples/store/src/components/account/OverviewTemplate/OverviewTemplate.module.css 展示了在 CSS 中通过@apply复用 Grid 工具类:

.overviewWapper { @apply col-span-1 row-span-2 flex h-full flex-1 flex-col gap-y-4; }

以及同文件中的grid grid-cols-3 grid-rows-2 gap-x-4(第 78 行),用一个 3 列 2 行的显式栅格组织数据展示区域。这印证了grid-rows-{n}col-span-{n}在真实后台/电商界面中的典型用法。

集成方式:CLI 与 PostCSS 两条路线

本文开头的npx tailwindcss ... --watch是 Tailwind CLI 路线;refine 的 Tailwind 示例则普遍采用 PostCSS 集成(每个示例都同时包含 postcss.config.js 与 tailwind.config.js),在 Vite/Next.js 构建链中由 PostCSS 插件处理 Tailwind。两种方式生成的类完全一致,选择哪一种取决于项目构建工具。

常见问题(FAQ)

Q:如何在 Tailwind CSS 中创建类似 CSS Grid 的响应式布局?A:将gridgrid-cols-{n}组合用于定义列,并为md:lg:等响应式前缀添加对应的列数变体,即可在指定断点调整布局。

Q:Flexbox 与 Grid 在 Tailwind 中的主要区别是什么?A:Flexbox 适合简单的一维布局(行或列),而 Grid 适合同时涉及行与列的复杂二维布局。本文的目标页面(导航 + 侧栏 + 主内容 + 页脚)就是典型的二维场景,应优先选择 Grid。

Q:如何在 Tailwind 中为栅格项添加间距?A:使用gap-{size}类,例如gap-4可为所有方向提供一致的间距;如需分别控制,用gap-x-{size}gap-y-{size}

Q:可以自定义 Tailwind Grid 可用的列数吗?A:可以。在tailwind.config.js中扩展gridTemplateColumns属性(以及配套的gridColumnStart/gridColumnEnd)即可生成自定义数量的列类,例如本文演示的 16 列栅格。

结语

本文使用 Tailwind 的 CSS Grid 类构建了一个简单的响应式布局:通过grid-cols-{n}grid-rows-{n}显式声明行列数,通过md:lg:等移动优先断点在不同屏幕宽度下重置布局,并用col-span-{n}col-start-{n}row-start-{n}row-end-{n}精确控制每个区块的尺寸与位置,甚至可以在断点切换时重排区块顺序。

更进一步,Tailwind 允许我们通过tailwind.config.js扩展生成类的规则——无论是把列数从 12 扩展到 16,还是像 refine 仓库的 store 示例 那样重定义整套断点——从而构建完全贴合业务需求的流畅响应式布局。这套“显式行列 + 断点前缀 + 扩展主题”的方法论,同样适用于 refine 构建后台面板、仪表盘等二维密集型界面时的布局工作。

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 2:00:52

欧姆龙NJ+EtherCAT实现24轴电池极片卷绕产线控制

接到一条电池极片卷绕生产线的控制改造项目那天&#xff0c;我第一反应是“又是个硬骨头”。整线加起来24台伺服电机&#xff0c;主控定了欧姆龙NJ系列&#xff0c;程序全部走ST语言&#xff0c;驱动器之间用EtherCAT总线串起来。说实话&#xff0c;24轴听起来吓人&#xff0c;…

作者头像 李华
网站建设 2026/9/10 2:00:33

CANN/ge AIPP色域转换参数设置

aclmdlSetAIPPCscParams 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、Te…

作者头像 李华
网站建设 2026/9/10 1:59:52

Python列表全解析:从底层原理到性能优化实战

Python 列表&#xff08;List&#xff09;几乎可以说是 Python 里最常用的数据结构&#xff0c;没有之一。无论是写脚本、做数据分析、写爬虫&#xff0c;还是搭 Web 后端&#xff0c;列表都是绕不开的基本功。很多人学 Python 的时候&#xff0c;列表的增删改查几天就上手了&a…

作者头像 李华
网站建设 2026/9/10 1:59:23

2026年AI真正革命:从AI编程到Agent落地的实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 1:59:20

离线AI代码审查:军工金融的数据安全与合规之道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 1:57:25

多旋翼任务飞行实战指南:从选型调参到炸机排查

简介&#xff1a;无人系统设计竞赛多旋翼任务飞行方向的一线实践资源&#xff0c;侧重真机平台上的飞控与感知算法开发&#xff0c;适合具备一定编程与嵌入式基础、准备参与同类赛事或开展自主导航项目的学习者。压缩包共2000个文件&#xff0c;约922MB&#xff0c;源码以C、Py…

作者头像 李华