文章目录
《CSS in Depth》新版封面
5.5 子网格布局 Subgrid
在前面的示例中,网格布局都只作用于 DOM 结构的两个层级:一是网格容器,二是其(直接)子元素。而对于某些设计,可能需要在更大层级范围内实现元素对齐。例如,要对齐同一祖先元素内的两个子元素,或者对它们设置相同的大小。这类设计的一个示例效果,如图 5.19 所示:
图 5.19 内部元素对齐的多张卡片布局效果
上述样式设计中,多张卡片都位于同一个网格内,因此水平方向排列整齐,高度也都相同。不仅如此,不同卡片的内部元素也实现了相互对齐:标题较短的两张卡片,通过增加顶部空间来与长标题那张对齐;每张卡片的正文段落相互间也实现了首行水平对齐;“Read more
”(即“阅读更多”)字样的超链接部分则实现了底边水平对齐。
要实现上述效果,最佳方案是利用一种全新的 CSS 特性,称为 子网格(subgrid)。有了子网格,一个网格不仅能放入另一个网格,其网格元素还能放置在外层网格的网格线上。本例中,每张卡片都占据了三行网格空间,并且各自的内容都与其对应的行相互对齐。图 5.20 高亮标出了参与页面布局的网格及其网格间隙。
图 5.20 高亮标注的网格线与网格间隙效果图
这时,就能看清卡片本身及其内部元素在同一个网格布局里进行定位的全过程了。
需要注意的是,子网格当前还是 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 created
the 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>The
Adventures of Tom Sawyer</i> and
<i>Adventures of Huckleberry Finn</i>.
He has been called “the father of
American 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>The
Iliad</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) {…}
。
本例演示了关键字 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 条水平网格线之间的子网格中。
第 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 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!