【CSS in Depth 2 精译_035】5.5 Grid 网格布局中的子网格布局(全新内容)
当前内容所在位置(可进入专栏查看其他译好的章节内容)
- 第一章 层叠、优先级与继承(已完结)
- 1.1 层叠
- 1.2 继承
- 1.3 特殊值
- 1.4 简写属性
- 1.5 CSS 渐进式增强技术
- 1.6 本章小结
- 第二章 相对单位(已完结)
- 2.1 相对单位的威力
- 2.2 em 与 rem
- 2.3 告别像素思维
- 2.4 视口的相对单位
- 2.5 无单位的数值与行高
- 2.6 自定义属性
- 2.7 本章小结
- 第三章 文档流与盒模型(已完结)
- 3.1 常规文档流
- 3.2 盒模型
- 3.3 元素的高度
- 3.4 负的外边距
- 3.5 外边距折叠
- 3.6 容器内的元素间距问题
- 3.7 本章小结
- 第四章 Flexbox 布局(已完结)
- 4.1 Flexbox 布局原理
- 4.2 弹性子元素的大小
- 4.3 弹性布局的方向
- 4.4 对齐、间距等细节处
- 4.5 本章小结
- 第五章 网格布局 ✔️
- 5.1 构建基础网格(已完结)
- 5.2 网格结构剖析 (上)
- 5.2.1 网格线的编号(下)
- 5.2.2 网格与 Flexbox 配合(下)
- 5.3 两种替代语法(已完结)
- 5.3.1 命名网格线
- 5.3.2 命名网格区域
- 5.4 显式网格与隐式网格(上)
- 5.4.1 添加变化 (中)
- 5.4.2 让网格元素填满网格轨道(下)
- 5.5 子网格(全新增补内容) ✔️
- 5.6 对齐相关的属性
文章目录
- 5.5 子网格布局 Subgrid
- 5.5.1 子网格的其他配置项 Additional options

《CSS in Depth》新版封面
译者按
学完 CSS 网格布局中的隐式网格(Implicit grid),这一节又迎来了一个非常实用的知识点:子网格(subgrid)。本节内容在 6 年前发行第 1 版时仅以一小段文字说明草草带过。经历了 6 年的技术沉淀,作者在第 2 版中索性另起一节,通过一个具体的案例,将子网格近年来的主流用法与最佳实践融入进来,最后还顺便提了一下尚在试验阶段的一个 CSS 新特性:砖石布局。窃以为这才是前端开发人员最应具备的职业素养:紧跟世界一流水平,熟悉业内最佳实践,只啃原汁原味的第一手资料。一起来先睹为快吧!
5.5 子网格布局 Subgrid
在前面的示例中,网格布局都只作用于 DOM 结构的两个层级:一是网格容器,二是其(直接)子元素。而对于某些设计,可能需要在更大层级范围内实现元素对齐。例如,要对齐同一祖先元素内的两个子元素,或者对它们设置相同的大小。这类设计的一个示例效果,如图 5.19 所示:

图 5.19 内部元素对齐的多张卡片布局效果
上述样式设计中,多张卡片都位于同一个网格内,因此水平方向排列整齐,高度也都相同。不仅如此,不同卡片的内部元素也实现了相互对齐:标题较短的两张卡片,通过增加顶部空间来与长标题那张对齐;每张卡片的正文段落相互间也实现了首行水平对齐;“Read more”(即“”)字样的超链接部分则实现了底边水平对齐。
要实现上述效果,最佳方案是利用一种全新的 CSS 特性,称为 子网格(subgrid)。有了子网格,一个网格不仅能放入另一个网格,其网格元素还能放置在外层网格的网格线上。本例中,每张卡片都占据了三行网格空间,并且各自的内容都与其对应的行相互对齐。图 5.20 高亮标出了参与页面布局的网格及其网格间隙。

图 5.20 高亮标注的网格线与网格间隙效果图
这时,就能看清卡片本身及其内部元素在同一个网格布局里进行定位的全过程了。
说明
图 5.20 是页面在 Firebox 浏览器中显示、并通过开发者工具 DevTools 标注出网格行的效果截图。在大多数浏览器中,想要调试出类似的网格效果,只需要打开检查面板(Inspector pane),然后找到目标元素旁边一个小小的“grid”字样的标签,单击它即可。Flexbox 布局也支持类似的功能。
需要注意的是,子网格当前还是 CSS 新出的一个功能特性,并不像网格那样得到广泛支持。虽然子网格出现在 Firefox 及 Safari 浏览器中已经有些时日了,但 Chrome 和 Edge 浏览器也是到 2023 年底才对该特性予以支持。关于子网格在浏览器中的最新支持情况,请参阅:https://caniuse.com/css-subgrid。
下面来演示上述布局的构建过程。首先创建一个新页面,并根据代码清单 5.12 更新页面 HTML 标记:
代码清单 5.12 三张作者信息卡片的网格布局 HTML 代码
<!doctype html>
<html lang="en-US">
<head><link href="styles.css" rel="stylesheet" type="text/css" />
</head>
<body><div class="author-bios"><!-- 主网格容器 --><div class="card"><!-- 卡片元素 --><h3>Sir Arthur Ignatius Conan Doyle</h3><div><p>A British writer and physician who createdthe fictional detective Sherlock Holmes.</p></div><div class="read-more"><a href="/conan-doyle">Read more</a></div></div><div class="card"><!-- 卡片元素 --><h3>Mark Twain</h3><div><p>An American author famous for <i>TheAdventures of Tom Sawyer</i> and<i>Adventures of Huckleberry Finn</i>.He has been called “the father ofAmerican literature.”</p></div><div class="read-more"><a href="/mark-twain">Read more</a></div></div><div class="card"><!-- 卡片元素 --><h3>Homer</h3><div><p>Author of the Greek epic poems <i>TheIliad</i> and <i>The Odyssey</i>.</p></div><div class="read-more"><a href="/homer">Read more</a></div></div></div>
</body>
</html>
如以上代码所示,实现该布局,需要重点处理好这三个层级的 DOM 元素对齐:
- 主网格容器:即
<div class="author-bios">元素; - 各网格元素:即三个
<div class="card">元素; - 卡片各自的子元素。
先来处理基础样式,包括背景色、间距、以及用于放置卡片的最顶层网格,如代码清单 5.13 所示。其中的样式可能除了个别网格声明还有点陌生(如果您正在熟悉网格布局)以外,其他大部分样式应该都已经很熟悉了:
代码清单 5.13 对作者卡片设置网格布局的样式代码
body {background-color: #eee;font-family: Helvetica, Arial, sans-serif;
}.author-bios {display: grid; /* 声明网格容器 */grid-template-columns: repeat(3, 1fr); /* 定义容器中的三个等宽网格列 */gap: 1em;max-inline-size: 800px;margin-inline: auto;
}.card {padding: 1rem;border-radius: 0.5rem;background-color: #fff;
}.card > h3 {margin-block: 0;padding-block-end: 0.5rem;border-block-end: 1px solid #eee;
}.read-more {margin-block-start: 1em;text-align: right;
}
以上样式生效后,三张卡片就会在水平方向一字排开,看上去已经非常接近最终效果了(如图 5.21 所示)。之后就剩子网格的具体设置了。

图 5.21 子网格生效前,三张作者信息卡的对齐效果图
要在页面中添加子网格,必须先在网格元素中声明 display: grid,这样就在外层网格中创建了一个内部网格。接着,在该内部网格的 grid-template-rows 和/或 grid-template-columns 中使用关键字 subgrid,表示其使用的应该为父网格的网格线。
相关 CSS 样式如代码清单 5.14 所示。请将以下样式更新到本地样式表:
代码清单 5.14 为卡片内容设置子网格的样式代码
.card {display: grid; /* 设置该卡片为网格容器 */gap: 0;grid-row: span 3; /* 令卡片横跨三行 */grid-template-rows: max-content auto max-content; /* 为不支持子网格的浏览器设置回退方案,指定网格行尺寸 */grid-template-rows: subgrid; /* 使用父网格的网格行 */padding: 1rem;border-radius: 0.5rem;background-color: #fff;
}.card > h3 {align-self: end; /* 令标题内容对齐到网格行的底部 */margin-block: 0;padding-block-end: 0.5rem;border-block-end: 1px solid #eee;
}
鉴于子网格仍是 CSS 一个较新的功能特性,这里特地为 grid-template-rows 提供了一套回退方案来效仿子网格的行为特征(该方案只能将三个“Read more”链接相对网格底边统一对齐,无法让标题部分相对各自的底边对齐)。还有一种备选方案,是将这些样式放到 CSS 特性查询语法中,检测当前环境对子网格的支持情况,例如:@supports (grid-template-rows: subgrid) {…}。
译注
关于上述回退方案的实际效果,原书一笔带过。这里觉得有必要配一张截图,方便与子网格的实际对齐效果进行比较:
补图1:当浏览器不支持子网格功能、备选回退方案生效时的页面效果
本例演示了关键字 subgrid 将元素对齐到父网格行的具体方法,您也可以声明 grid-template-columns: subgrid 让元素根据父网格的列对齐,甚至同时对行与列对齐。此外,还可以在 DOM 树中延续这种写法,将子网格嵌套进另一个子网格中。
5.5.1 子网格的其他配置项 Additional options
子网格中的网格线编号、网格线名称以及网格区域名称均从父网格中继承而来,因此可以利用它们在子网格中放置元素。例如,以下样式会将所有卡片标题放在第二行:
.card {grid-template-rows: subgrid [line1] [line2] [line3] [line4];
}
以上这些命名网格线,与前面 5.3.1 小节介绍的一样,它们的含义及用法与在普通网格上定义的网格线均相同。例如,声明 grid-row: line3 / line4 会将元素放置在第 3 条和第 4 条水平网格线之间的子网格中。
注意
未来可能出现的一个新网格特性功能,叫做 砖石布局(masonry layout)(译注:发音为
/ˈmeɪsənri/)。它是一种在相册场景下非常流行的布局方式,但需要借助 JavaScript 才能实现其效果。在砖石布局中,网格元素被放置在一系列宽度相等的网格列中,并且允许网格元素根据自身内容决定其高度,因此网格行不一定对齐。具体情况可以参考维也纳前端开发者 Manuel Matuzović 发表的这篇概述:Day 72: the masonry-auto-flow property
译注
为方便查阅,特将 5.3.1 节介绍命名网格线时自行补充的网格布局效果展示如下 :
补图2 除了最后一条水平网格线,其余都被命名为 “row”
对应的样式设置如下(详见 5.3.1 节:命名网格线):
.container { display: grid; grid-template-columns:/* 分别给每条垂直网格线命名 */[left-start] 2fr[left-end right-start] 1fr[right-end]; /* 将水平网格线命名为 row */ grid-template-rows: repeat(4, [row] auto); gap: var(--gap-size); max-inline-size: 1080px; margin-inline: auto; }header, nav { grid-column: left-start / right-end; grid-row: span 1; }.main { grid-column: left; /* 跨越 left-start 到 left-end 之间的区域 */ grid-row: row 3 / span 2; /* 从第三个命名网格线 row 开始放置元素,并跨越两个网格轨道 */ }.sidebar-top { grid-column: right; /* 跨越 right-start 到 right-end 之间的区域 */ grid-row: 3 / 4; }.sidebar-bottom { grid-column: right; /* 跨越 right-start 到 right-end 之间的区域 */ grid-row: 4 / 5; }此外,关于上面提到的 砖石布局,也可以参考 MDN 的 线上官方文档,这里只补充其中一个示例效果图:
补图3 MDN 官方文档给出的一个砖石布局效果图
关于《CSS in Depth》(中译本书名《深入解析 CSS》)
| 第 1 版 | 第 2 版 | |
|---|---|---|
| 读者评分 | 原版:4.7(亚马逊);中文版:9.3(豆瓣) | 原版:5.0(亚马逊);中文版:暂无,待出版 |
| 出版时间 | 原版:2018 年 3 月;中文版:2020 年 4 月 | 原版:2024 年 7 月;中文版:暂无,待出版 |
| 原价 | 原版:$44.99;中文版:¥139.00 | 原版:$59.99;中文版:暂无,待出版 |
| 现价 | 原版:$36.49;中文版:¥52.54 起步 | 原版:$52.09;中文版:暂无,待出版 |
| 原版国内预订 | 起步价 ¥461.00 | 起步价 ¥750.00 |
本专栏为该书第 2 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!
相关文章:
【CSS in Depth 2 精译_035】5.5 Grid 网格布局中的子网格布局(全新内容)
当前内容所在位置(可进入专栏查看其他译好的章节内容) 第一章 层叠、优先级与继承(已完结) 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位(已完结) 2.1 相对…...
Java是怎么处理死锁的
文章目录 避免死锁避免嵌套锁资源进行排序超时锁 检测死锁通过Java提供的API检查死锁情况jStack监控工具 Java 本身没有内置的机制自动处理死锁问题,但可以采取一些策略和技术来检测和避免死锁。 避免死锁 避免嵌套锁 尽可能减少嵌套锁操作,避免在一个…...
Effective Java 学习笔记 方法签名设计
目录 谨慎选择方法名称 不要过于追求提供便利的快捷方法 避免过长的参数列表 对于参数类型优先使用接口而不是类 对于boolean参数,要优先使用两个元素的枚举类型 本文接续前一篇文章聚焦Java方法签名的设计,方法签名包括了方法的输入和输出参数以及…...
毛利超70%、超70+智驾客户,这家AI数据训练服务商刚刚止亏
AI训练数据服务第一股海天瑞声终于迎来了“曙光”。 日前,海天瑞声发布2024年半年报显示,上半年其实现营收9242.63万,同比增长24.13%;实现净利润41.64 万元,不过同比去年同期的亏损1724.14万元,扭亏为盈。…...
本地部署高颜值某抑云音乐播放器Splayer并实现无公网IP远程听歌
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
图像压缩编码(4)--H.26x系列视频压缩编码_2
目录 H.261 视频编码标准 H.261的编码与解码 1) 帧内/帧间编码 2)运动补偿 3)量化 4)环路滤波器 5)缓存器 压缩数据的分层 数据复用结构 H.264的编码与解码 H.261 视频编码标准 实际应用时,要求有…...
JS渲染锻炼输入表单
前言 上篇文章为大家展现了好看的信息窗口,接下来我们跟着流程图看下一步 之前我们的带点击事件已经添加完毕,下一步就是当用户点击的时候,渲染锻炼形式,当然这是一个标签,可以提供给用户输入锻炼形式 实例 ● 我…...
proteus仿真学习(1)
一,创建工程 一般选择默认模式,不配置pcb文件 可以选用芯片型号也可以不选 不选则从零开始布局,没有初始最小系统。选用则有初始最小系统以及基础的main函数 本次学习使用从零开始,不配置固件 二,上手软件 1.在元件…...
决策树+随机森林模型实现足球大小球让球预测软件
文章目录 前言一、决策树是什么?二、数据收集与整理1.数据收集2.数据清洗3.特征选择 三、决策树构建3.1绘制训练数据图像3.2 训练决策树模型3.3 依据模型绘制决策树的决策边界3.4 树模型可视化 四、模型预测五、随机森林模型总结 前言 之前搞足球数据分析的时候&…...
31省市农业地图大数据
1.北京市 谷类作物种植结构(万亩) 农作物种植结构(万亩) 2.天津市 谷类作物种植结构(万亩) 农作物种植结构(万亩) 3.黑龙江省 谷类作物种植结构(万亩) 农作物…...
http请求包含什么
HTTP请求通常包含以下几个主要部分: 请求行(Request Line): 包含请求方法(如 GET、POST、PUT、DELETE 等)、请求的目标 URI 和 HTTP 版本。例如:GET /index.html HTTP/1.1 请求头部(…...
【基础算法总结】模拟篇
目录 一,算法介绍二,算法原理和代码实现1576.替换所有的问号495.提莫攻击6.Z字形变换38.外观数列1419.数青蛙 三,算法总结 一,算法介绍 模拟算法本质就是"依葫芦画瓢",就是在题目中已经告诉了我们该如何操作…...
《深度学习》PyTorch 手写数字识别 案例解析及实现 <下>
目录 一、回顾神经网络框架 1、单层神经网络 2、多层神经网络 二、手写数字识别 1、续接上节课代码,如下所示 2、建立神经网络模型 输出结果: 3、设置训练集 4、设置测试集 5、创建损失函数、优化器 参数解析: 1)para…...
【笔记】材料分析测试:晶体学
晶体与晶体结构Crystal and Crystal Structure 1.晶体主要特征 固态物质可以分为晶态和非晶态两大类,分别称为晶体和非晶体。 晶体和非晶体在微观结构上的区别在于是否具有长程有序。 晶体(长程有序)非晶(短程有序)…...
飞塔Fortigate7.4.4的DNS劫持功能
基础网络配置、上网策略、与Server的VIP配置(略)。 在FortiGate上配置DNS Translation,将DNS请求结果为202.103.12.2的DNS响应报文中的IP地址修改为Server的内网IP 10.10.2.100。 config firewall dnstranslationedit 1set src 2.13.12.2set…...
Unity 设计模式 之 行为型模式 -【状态模式】【观察者模式】【备忘录模式】
Unity 设计模式 之 行为型模式 -【状态模式】【观察者模式】【备忘录模式】 目录 Unity 设计模式 之 行为型模式 -【状态模式】【观察者模式】【备忘录模式】 一、简单介绍 二、状态模式(State Pattern) 1、什么时候使用状态模式 2、使用状态模式的…...
【RabbitMQ】RabbitMQ 的概念以及使用RabbitMQ编写生产者消费者代码
目录 1. RabbitMQ 核心概念 1.1生产者和消费者 1.2 Connection和Channel 1.3 Virtual host 1.4 Queue 1.5 Exchange 1.6 RabbitMO工作流程 2. AMQP 3.RabbitMO快速入门 3.1.引入依赖 3.2.编写生产者代码 3.3.编写消费者代码 4.源码 1. RabbitMQ 核心概念 在安装…...
openmv与stm32通信
控制小车视觉循迹使用 OpenMV 往往是不够的。一般使用 OpenMV 对图像进行处理,将处理过后的数据使用串口发送给STM32,使用STM32控制小车行驶。本文主要讲解 OpenMV 模块与 STM32 间的串口通信以及两种循迹方案,分别是划分检测区域和线性回归。…...
C++ STL全面解析:六大核心组件之一----序列式容器(vector和List)(STL进阶学习)
目录 序列式容器 Vector vector概述 vector的迭代器 vector的数据结构 vector的构造和内存管理 vector的元素操作 List List概述 List的设计结构 List的迭代器 List的数据结构 List的内存构造 List的元素操作 C标准模板库(STL)是一组高效的…...
【c数据结构】OJ练习篇 帮你更深层次理解链表!(相交链表、相交链表、环形链表、环形链表之寻找环形入口点、判断链表是否是回文结构、 随机链表的复制)
目录 一. 相交链表 二. 环形链表 三. 环形链表之寻找环形入口点 四. 判断链表是否是回文结构 五. 随机链表的复制 一. 相交链表 最简单粗暴的思路,遍历两个链表,分别寻找是否有相同的对应的结点。 我们对两个链表的每个对应的节点进行判断比较&…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)
+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...


