🤙《中级前端进阶方向指南》

《中级前端进阶方向 第一步)JavaScript 微任务 / 宏任务机制》

《中级前端进阶方向 第二步)深入事件循环(Event Loop)》

《中级前端进阶方向 第三步)深入javascript原型链,附学习代码》

《中级前端进阶方向 第四步)深入javascript 闭包、this 、作用域提升,附学习案例源码》

《​​中级前端进阶方向 第五步)深入 javascript高级特性Proxy,附学习案例源码》

《​​中级前端进阶方向 第六步)深入 javascript 高级特性Generator生成器,附案例源码》
《​​中级前端进阶方向 第七步)深入 javascript 高级特性Async/Await,附源码》

《​​中级前端进阶方向 第八步)深入 javascript 高级特性 Promise,附案例源码》

《​​中级前端进阶方向 第九步)深入 javascript 高级特性 模块化 与 装饰器,附案例源码》

《中级前端进阶方向 第十步)深入 浏览器性能优化(渲染机制、内存泄漏..),附案例源码》


--🖍《CSS》-----------------------------------------------------------------------------------------

《中级前端进阶 第十一步) 深入CSS3 新特性,附源码,可视化演示等》

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


--🖍《延伸扩展》-----------------------------------------------------------------------------------------
《中级前端进阶方向 延伸扩展一)javascript 私有状态/工厂函数/回调中保持局部状态/防抖与节流/IIFE 捕获》

《中级前端进阶方向 延伸扩展二) Promise API 概览,可视化演示页面》


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-fillauto-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 | densedense 会尝试填补“洞”实现紧凑填充,但可能改变视觉顺序)。


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 / endgrid-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 的布局变得直观可维护。建议步骤:

  1. 在新页面优先考虑 Grid 作为主布局工具(结合 Flex 处理局部的一维场景)。

  2. 学会用 repeat(auto-fill/minmax) 做响应画廊;用 grid-template-areas 做语义化布局模板。

  3. 在大型项目中对 subgrid / masonry 的使用先做兼容检测(Can I Use / MDN),再决定是否采用。\


18 可视化案例源码

包含以下功能:

  1. 网格模板列 (grid-template-columns):可以输入任意有效的CSS值,如"1fr 1fr 1fr"或"repeat(3, 1fr)"

  2. 网格模板行 (grid-template-rows):控制网格行的大小

  3. 间距 (gap):使用滑块控制网格项之间的间距

  4. 对齐方式:控制网格内容在容器内的对齐方式

  5. 自动布局:控制自动放置算法

  6. 实时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>

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐