中级前端进阶 第十三步) 深入CSS3 Grid布局,附源码,可视化演示等

《中级前端进阶方向 第一步)JavaScript 微任务 / 宏任务机制》
《中级前端进阶方向 第二步)深入事件循环(Event Loop)》
《中级前端进阶方向 第三步)深入javascript原型链,附学习代码》
《中级前端进阶方向 第四步)深入javascript 闭包、this 、作用域提升,附学习案例源码》
《中级前端进阶方向 第五步)深入 javascript高级特性Proxy,附学习案例源码》
《中级前端进阶方向 第六步)深入 javascript 高级特性Generator生成器,附案例源码》
《中级前端进阶方向 第七步)深入 javascript 高级特性Async/Await,附源码》《中级前端进阶方向 第八步)深入 javascript 高级特性 Promise,附案例源码》
《中级前端进阶方向 第九步)深入 javascript 高级特性 模块化 与 装饰器,附案例源码》
《中级前端进阶方向 第十步)深入 浏览器性能优化(渲染机制、内存泄漏..),附案例源码》
--🖍《CSS》-----------------------------------------------------------------------------------------《中级前端进阶 第十一步) 深入CSS3 新特性,附源码,可视化演示等》
《中级前端进阶 第十二步) 深入CSS3 Flex布局,附源码,可视化演示等》
--🖍《延伸扩展》-----------------------------------------------------------------------------------------
《中级前端进阶方向 延伸扩展一)javascript 私有状态/工厂函数/回调中保持局部状态/防抖与节流/IIFE 捕获》
1 — 基本概念
-
Grid container:定义了
display: grid/inline-grid的元素。 -
Grid item:Grid 容器的直接子元素(只有直接子元素参与 Grid 布局)。
-
Grid line:网格的“线”,有列线(vertical)和行线(horizontal),以数字或命名引用。
-
Grid track:在两条相邻 grid line 之间的一条行或列(即“列/行轨道”)。
-
Grid cell:行和列轨道的交叉单元(最小格子)。
-
Grid area:由若干相连的 grid cells 组成的矩形区域(可用
grid-template-areas给名字)。
Grid 是二维布局(同时控制行和列),适合页面整体布局或复杂组件内的区域排列。MDN 的 Grid 总览是权威参考MDN Web Docs
2 — 创建网格:最常用属性(容器与子项)
容器主要属性(最常用的写法):
.container {
display: grid; /* 或 inline-grid */
grid-template-columns: 200px 1fr 100px; /* 明确定义列(轨道) */
grid-template-rows: auto 1fr auto; /* 行定义 */
gap: 16px 24px; /* 行间距 row-gap / 列间距 column-gap */
justify-items: stretch; /* 单元格内项目在行方向对齐 */
align-items: start; /* 单元格内项目在列方向对齐 */
justify-content: center; /* 整个 grid 在容器内的主轴(行)对齐 */
align-content: start; /* grid 多行时整体在交叉轴对齐 */
grid-auto-flow: row dense; /* 隐式网格元素如何自动放置 */
}
子元素常用属性:
.item {
grid-column: 2 / 4; /* 从列线 2 到 4(不包含 4) */
grid-row: 1 / span 2; /* 从行 1 开始,跨 2 行 */
grid-area: header; /* 若定义了命名区域可直接放置 */
justify-self: center; /* 覆盖容器的 justify-items */
align-self: end;
}
3 — 轨道尺寸(track sizing):fr / px / %, auto / minmax / min-content / max-content / fit-content
-
fr(fraction):剩余空间分配单位,典型写法1fr 2fr表示按份额分配剩余空间。 -
auto:基于内容的自动大小。 -
minmax(min, max):指定轨道有最小与最大边界(对响应式很关键)。MDN 对minmax()有详尽解释。MDN Web Docs -
min-content/max-content:基于内容的固有最小/最大尺寸(用于更精细的 intrinsic sizing)。 -
fit-content()/fit-content()与clamp一起用:用于最大值剪裁。
示例(响应式网格单行):
.grid {
grid-template-columns: repeat(3, 1fr); /* 三列等分 */
}
/* 自适应卡片列:最小 200px,最大占剩余空间 */
.gallery {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
4 — repeat(), auto-fill vs auto-fit(响应式常用)
-
repeat(n, ...)简写重复轨道定义。 -
auto-fill和auto-fit配合minmax()与repeat()能实现「流式响应格子」:-
auto-fill会尽量把尽可能多的列塞入行(即使某些列为空), -
auto-fit在容器较宽时会让空余列“折叠”以便项目拉伸占满空间(实际差别在容器空间多余时)。
两者差异见实战讨论(经典解释在 CSS-Tricks)。css-tricks.com
-
常见写法(响应式画廊):
.gallery {
display: grid;
gap: 16px;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
5 — 命名区域与 line-based 放置(直观布局)
grid-template-areas 可以用可读的区域名称画出布局模板,便于实现 header / sidebar / content / footer 等常见布局:
.layout {
display:grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"left main right"
"footer footer footer";
gap: 12px;
}
.header { grid-area: header; }
.left { grid-area: left; }
.main { grid-area: main; }
.right { grid-area: right; }
.footer { grid-area: footer; }
grid-area 也可以用数字/line 名称来放置(grid-column: 1 / 3)。
6 — 隐式网格(implicit grid)与 grid-auto-*
当放置的 item 超出明确定义的轨道时,浏览器会创建隐式轨道(implicit tracks)。控制它们的属性:
-
grid-auto-rows/grid-auto-columns:隐式行/列的大小。 -
grid-auto-flow:控制自动放置行为(row | column | dense,dense会尝试填补“洞”实现紧凑填充,但可能改变视觉顺序)。
7 — auto-placement 算法(简要)
-
如果你给部分 items 指定位置,其余则由 自动放置算法 根据可用空位和
grid-auto-flow规则放置。 -
grid-auto-flow: row(默认)按行优先填充;加上dense会尝试回填空位(但可能改变顺序)。
理解自动放置可以帮助减少显式位置声明的数量并实现流式布局。
8 — Subgrid(子网格)
-
Subgrid 允许嵌套的子网格“继承”父网格的行或列定义(对复杂组件内部对齐非常有用)。MDN 有专门章节说明
subgrid的用途与语义。MDN Web Docs -
兼容性注意:
subgrid在部分浏览器/版本中支持度不同(在考虑广泛兼容的项目中使用时需检测)。Can I Use 提供实时支持表(查看是否可在目标用户群中放心使用)。Can I Use
示例:
.parent {
display: grid;
grid-template-columns: 1fr 2fr;
}
.child {
display: grid;
grid-template-columns: subgrid; /* 继承父列定义 */
}
9 — 常见实战模板(代码可直接复制)
A. 经典三栏布局(Header / 3-col / Footer)
<div class="page">
<header class="hdr">Header</header>
<aside class="left">Left</aside>
<main class="main">Main</main>
<aside class="right">Right</aside>
<footer class="ftr">Footer</footer>
</div>
.page {
display:grid;
grid-template-columns: 220px 1fr 240px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"hdr hdr hdr"
"left main right"
"ftr ftr ftr";
gap: 16px;
min-height: 100vh;
}
.hdr { grid-area: hdr; }
.left { grid-area: left; }
.main { grid-area: main; }
.right { grid-area: right; }
.ftr { grid-area: ftr; }
B. Holy-Grail(响应版)— 左侧固定、主列自适应、右侧浮动
响应时把列折叠到单列:
@media (max-width: 800px) {
.page {
grid-template-columns: 1fr;
grid-template-areas:
"hdr"
"left"
"main"
"right"
"ftr";
}
}
C. 响应画廊(自动换行、等距)
.gallery {
display:grid;
gap:12px;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
10 — Intrinsic sizing(内容驱动)与常见陷阱
-
默认情况下轨道尺寸会受内容固有尺寸影响(
min-content/max-content)。当你想要忽略内容并强制均分时,用minmax(0, 1fr)或将min-width:0/min-height:0用在子项上来允许收缩。 -
常见问题:在子项内有长文本或不可压缩元素(如图片)时,网格轨道可能无法按预期收缩 —— 解决办法是给子项设
min-width: 0或让图片max-width: 100%。
11 — 可访问性与 DOM 顺序
-
Grid 可视化顺序(通过
grid-column/order/grid-auto-flow:dense)可能与文档的 DOM 顺序不一致。键盘导航与屏幕阅读器通常遵循 DOM 顺序,因此不要仅用 Grid 视觉重排替代语义重排。对于需要改变阅读顺序的场景,使用 ARIA 或调整 DOM 更合适。
12 — 性能、CSS 混用与实际建议
-
Grid 本身性能良好,但复杂网格 + 大量 DOM 更新会触发重排(reflow)。避免在动画中频繁调整会触发布局的属性(像 width/height/top/left);若是动画,优先使用
transform/opacity。 -
Grid 与 Flex 各有侧重:Flex 擅长一维(导航、工具条)、Grid 擅长二维(页面主布局、复杂卡片网格)。混合使用时让职责分明(外层 Grid、内层 item 使用 Flex 处理一维排列)。
-
使用
gap而不是在子元素上手动加 margin,可以减少样式复杂度。
13 — 调试技巧(DevTools)
-
Chrome / Firefox DevTools 都提供 Grid overlay(高亮网格轨道、行/列线、区域名称与行号),非常有助于排查放置/跨列/跨行问题。
-
打开 DevTools → Elements 选中 Grid 容器 → 在 Styles 面板中会看到 Grid 的小图标(点击可显示 overlay 控制)。
-
通过给 grid line 命名(
[name]语法)或grid-template-areas提高可读性便于调试。
14 — 进阶话题与兼容性提醒
-
Subgrid:对于需要子元素与父网格精确对齐的组件非常有用,但在老旧浏览器上支持不全(使用前应用 Can I Use 检查目标市场支持)。MDN Web DocsCan I Use
-
Masonry(瀑布流):Grid Level 3 提案包含对“masonry”风格布局的讨论与方案,但不同引擎的态度与实现方式不一致(若要跨浏览器支持,当前仍需借助 JS 或 CSS column 的替代方案),可以参考 WebKit/Chrome 社区的讨论。WebKitMDN Web Docs
15 — 快速 Cheat-Sheet(最常用属性速查)
容器:
-
display: grid | inline-grid -
grid-template-columns: ... -
grid-template-rows: ... -
grid-template-areas: "a b" "c d"; -
gap,row-gap,column-gap -
grid-auto-flow: row | column | row dense -
justify-items,align-items,place-items(简写) -
justify-content,align-content,place-content(容器整体对齐)
子项:
-
grid-column: start / end或grid-column: span 2 -
grid-row: start / end -
grid-area: name(或row-start / column-start / row-end / column-end) -
justify-self,align-self,place-self
16 — 常见问题与解决方法(FAQ)
Q:为什么我的列不等分?
A:检查是否使用了 minmax(0, 1fr)(而不是 minmax(auto, 1fr)),并给含有长内容的子项 min-width: 0,并确保图片 max-width: 100%。
Q:如何让网格项垂直居中?
A:容器 align-items: center; 或子项 align-self: center;。
Q:需要实现瀑布流(Masonry),用 Grid 吗?
A:Grid Level 3 在提案中讨论了 masonry,但目前跨浏览器支持不完全。推荐短期用 column 或 JS Masonry 库/布局策略实现,或者在确认目标浏览器支持后使用原生方案。MDN Web Docs
17 — 结语与下一步建议
CSS Grid 是现代布局最强大的工具之一:二维布局 + 可读的模板语法 + 强大的响应能力,能把以前需要大量嵌套和 hack 的布局变得直观可维护。建议步骤:
-
在新页面优先考虑 Grid 作为主布局工具(结合 Flex 处理局部的一维场景)。
-
学会用
repeat(auto-fill/minmax)做响应画廊;用grid-template-areas做语义化布局模板。 -
在大型项目中对
subgrid/masonry的使用先做兼容检测(Can I Use / MDN),再决定是否采用。\
18 可视化案例源码
包含以下功能:
-
网格模板列 (grid-template-columns):可以输入任意有效的CSS值,如"1fr 1fr 1fr"或"repeat(3, 1fr)"
-
网格模板行 (grid-template-rows):控制网格行的大小
-
间距 (gap):使用滑块控制网格项之间的间距
-
对齐方式:控制网格内容在容器内的对齐方式
-
自动布局:控制自动放置算法
-
实时CSS代码显示:显示当前网格的CSS代码
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS Grid布局可视化演示</title> <style> * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; color: #333; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); min-height: 100vh; padding: 20px; } .container { max-width: 1200px; margin: 0 auto; display: grid; grid-template-columns: 1fr 350px; gap: 30px; } header { grid-column: 1 / -1; text-align: center; margin-bottom: 20px; padding: 20px; background: rgba(255, 255, 255, 0.8); border-radius: 10px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); } h1 { color: #2c3e50; margin-bottom: 10px; } .description { color: #7f8c8d; max-width: 800px; margin: 0 auto; } .demo-area { background: white; padding: 25px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); } .controls { background: white; padding: 25px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); overflow-y: auto; max-height: 80vh; } .grid-container { display: grid; grid-template-columns: repeat(4, 1fr); grid-auto-rows: minmax(100px, auto); gap: 15px; padding: 15px; background: #ecf0f1; border: 2px solid #bdc3c7; border-radius: 5px; min-height: 400px; transition: all 0.3s ease; } .grid-item { background: #3498db; color: white; display: flex; align-items: center; justify-content: center; font-weight: bold; border-radius: 5px; transition: all 0.3s ease; padding: 10px; } .grid-item:nth-child(2n) { background: #9b59b6; } .grid-item:nth-child(3n) { background: #2ecc71; } .grid-item:nth-child(4n) { background: #e74c3c; } .control-group { margin-bottom: 20px; padding-bottom: 15px; border-bottom: 1px solid #eee; } h3 { margin-bottom: 12px; color: #2c3e50; } label { display: block; margin: 8px 0 5px; font-weight: 500; } input[type="range"] { width: 100%; } select, input[type="text"] { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; } .value-display { display: inline-block; min-width: 40px; text-align: right; font-weight: 600; color: #3498db; } .code-example { background: #2c3e50; color: #ecf0f1; padding: 15px; border-radius: 5px; font-family: monospace; margin-top: 20px; overflow-x: auto; } .property-name { color: #3498db; } .property-value { color: #2ecc71; } .grid-lines { position: absolute; top: 0; left: 0; right: 0; bottom: 0; pointer-events: none; } @media (max-width: 900px) { .container { grid-template-columns: 1fr; } } </style> </head> <body> <div class="container"> <header> <h1>CSS Grid 布局可视化演示</h1> <p class="description">通过此交互式演示了解CSS Grid布局的工作原理。调整右侧的控制选项来实时查看Grid属性如何影响布局。</p> </header> <main class="demo-area"> <div class="grid-container"> <div class="grid-item">1</div> <div class="grid-item">2</div> <div class="grid-item">3</div> <div class="grid-item">4</div> <div class="grid-item">5</div> <div class="grid-item">6</div> <div class="grid-item">7</div> <div class="grid-item">8</div> <div class="grid-item">9</div> <div class="grid-item">10</div> <div class="grid-item">11</div> <div class="grid-item">12</div> </div> </main> <aside class="controls"> <div class="control-group"> <h3>网格模板列 (grid-template-columns)</h3> <label for="templateColumns">值: <span id="columnsValue" class="value-display">1fr 1fr 1fr 1fr</span></label> <input type="text" id="templateColumns" value="1fr 1fr 1fr 1fr"> <p>定义网格中的列数和每列的宽度。例如: 1fr 200px 1fr 或 repeat(3, 1fr)</p> </div> <div class="control-group"> <h3>网格模板行 (grid-template-rows)</h3> <label for="templateRows">值: <span id="rowsValue" class="value-display">auto</span></label> <input type="text" id="templateRows" value="auto"> <p>定义网格中的行数和每行的高度。例如: 100px auto 200px</p> </div> <div class="control-group"> <h3>间距 (gap)</h3> <label for="gap">行间距和列间距: <span id="gapValue" class="value-display">15px</span></label> <input type="range" id="gap" min="0" max="30" value="15"> <p>定义网格项之间的间距大小</p> </div> <div class="control-group"> <h3>对齐方式</h3> <label for="justifyContent">主轴对齐 (justify-content)</label> <select id="justifyContent"> <option value="start">start</option> <option value="end">end</option> <option value="center" selected>center</option> <option value="stretch">stretch</option> <option value="space-around">space-around</option> <option value="space-between">space-between</option> <option value="space-evenly">space-evenly</option> </select> <label for="alignContent">交叉轴对齐 (align-content)</label> <select id="alignContent"> <option value="start">start</option> <option value="end">end</option> <option value="center" selected>center</option> <option value="stretch">stretch</option> <option value="space-around">space-around</option> <option value="space-between">space-between</option> <option value="space-evenly">space-evenly</option> </select> </div> <div class="control-group"> <h3>自动布局</h3> <label for="autoFlow">自动放置算法 (grid-auto-flow)</label> <select id="autoFlow"> <option value="row">row</option> <option value="column">column</option> <option value="dense">dense</option> </select> <p>控制自动放置的网格项如何流入网格</p> </div> <div class="code-example"> <p>当前Grid CSS代码:</p> <pre><code>.grid-container { <span class="property-name">display</span>: <span class="property-value">grid</span>; <span class="property-name">grid-template-columns</span>: <span class="property-value" id="codeColumns">1fr 1fr 1fr 1fr</span>; <span class="property-name">grid-template-rows</span>: <span class="property-value" id="codeRows">auto</span>; <span class="property-name">gap</span>: <span class="property-value" id="codeGap">15px</span>; <span class="property-name">justify-content</span>: <span class="property-value" id="codeJustify">center</span>; <span class="property-name">align-content</span>: <span class="property-value" id="codeAlign">center</span>; <span class="property-name">grid-auto-flow</span>: <span class="property-value" id="codeFlow">row</span>; }</code></pre> </div> </aside> </div> <script> // 获取DOM元素 const gridContainer = document.querySelector('.grid-container'); const templateColumns = document.getElementById('templateColumns'); const templateRows = document.getElementById('templateRows'); const gap = document.getElementById('gap'); const justifyContent = document.getElementById('justifyContent'); const alignContent = document.getElementById('alignContent'); const autoFlow = document.getElementById('autoFlow'); // 显示值的元素 const columnsValue = document.getElementById('columnsValue'); const rowsValue = document.getElementById('rowsValue'); const gapValue = document.getElementById('gapValue'); // 代码示例中的元素 const codeColumns = document.getElementById('codeColumns'); const codeRows = document.getElementById('codeRows'); const codeGap = document.getElementById('codeGap'); const codeJustify = document.getElementById('codeJustify'); const codeAlign = document.getElementById('codeAlign'); const codeFlow = document.getElementById('codeFlow'); // 初始化 updateGrid(); // 事件监听 templateColumns.addEventListener('input', updateGrid); templateRows.addEventListener('input', updateGrid); gap.addEventListener('input', updateGrid); justifyContent.addEventListener('change', updateGrid); alignContent.addEventListener('change', updateGrid); autoFlow.addEventListener('change', updateGrid); // 更新网格样式 function updateGrid() { // 更新网格属性 gridContainer.style.gridTemplateColumns = templateColumns.value; gridContainer.style.gridTemplateRows = templateRows.value; gridContainer.style.gap = `${gap.value}px`; gridContainer.style.justifyContent = justifyContent.value; gridContainer.style.alignContent = alignContent.value; gridContainer.style.gridAutoFlow = autoFlow.value; // 更新显示的值 columnsValue.textContent = templateColumns.value; rowsValue.textContent = templateRows.value; gapValue.textContent = `${gap.value}px`; // 更新代码示例 codeColumns.textContent = templateColumns.value; codeRows.textContent = templateRows.value; codeGap.textContent = `${gap.value}px`; codeJustify.textContent = justifyContent.value; codeAlign.textContent = alignContent.value; codeFlow.textContent = autoFlow.value; } </script> </body> </html>
更多推荐


所有评论(0)