【CSS in Depth 2 精译_030】5.2 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.2.1 网格线的编号](#5.2.1 网格线的编号)
      • [5.2.2 网格与 Flexbox 配合](#5.2.2 网格与 Flexbox 配合)

《CSS in Depth》新版封面

5.2.1 网格线的编号

网格轨道定义好后,下一步就是将各网格元素放置到特定的位置。浏览器给网格中的每条网格线都分配了如图 5.7 所示的编号。有了它们 CSS 就能将每个元素指定到具体位置。

图 5.7 网格线从左上角的 1 开始编号;负数则是从右下角的 -1 开始编号。

元素位置的指定需要用到 grid-columngrid-row 这两个属性。若网格元素是沿垂直方向从 1 号网格线跨越到 3 号线,则设置为 grid-column: 1 / 3;若是沿水平方向从 3 号网格线跨越到 5 号线,则设置为 grid-row: 3 / 5。这两个属性一起就能将元素放置到指定的网格区域。

示例页中的网格元素也是按如下样式摆放到位的:

css 复制代码
.main {
  grid-column: 1 / 2;
  grid-row: 3 / 5;
}

.sidebar-top {
  grid-column: 2 / 3;
  grid-row: 3 / 4;
}

.sidebar-bottom {
  grid-column: 2 / 3;
  grid-row: 4 / 5;
}

这段代码将 main 元素放到了第一列(即 1 号和 2 号垂直网格线之间),并纵向跨越第 3 ~ 4 行(即 3 号与 5 号水平网格线之间)。侧边栏的两个内容板块则都放置在靠右那一列(即 2 号与 3 号垂直网格线之间),纵向上分属第三行和第四行网格单元。

注意

这些属性其实是简写属性:grid-columngrid-column-startgrid-column-end 的简写形式;而 grid-row 则是 grid-row-startgrid-row-end 的简写形式。中间的斜线仅用于区分简写属性中的两个属性值,斜线前后的空格不做强制要求。

而定位 headernav 的规则集略有不同。本例使用了相同的规则集同时定位这两个元素:

css 复制代码
header,
nav {
  grid-column: 1 / 3;
  grid-row: span 1;
}

上述样式用了前面介绍的 grid-column 将元素铺满整个网格的宽度。其实还可以用另一个特殊关键字 span 来设置 grid-rowgrid-column(这里用在了 grid-row 上)。该关键字会告知浏览器元素需要占据一条网格轨道。由于未指明具体哪一行,因此网格元素会根据其 布局算法(placement algorithm ,自动放置放置到网格上可以容纳该元素的第一处可用空间,即本例的第一行与第二行。本章稍后会详细介绍该算法。

5.2.2 网格与 Flexbox 配合

学了网格布局,开发人员常常会问 Flexbox 和网格布局是否只能二选一。答案是大可不必。它们其实是互补关系。二者在很大程度上是一同开发出来的,虽然功能上存在部分重叠,但它们各自擅长的场景不一样。设计中究竟是用弹性盒布局还是网格布局,最终取决于具体的需求和应用场景。这两种布局方式有以下两个重要区别:

  • Flexbox 本质上是一维的,而网格是二维的;
  • Flexbox 是以内容为切入点由内而外工作的,而网格是以布局为切入点从外向内工作的。

由于具备一维属性,Flexbox 更适合用在由相似元素组成的行(或列)上。尽管支持用 flex-wrap 换行,但 Flexbox 无法让上一行元素同下一行对齐。相反,网格的二维属性则很好地解决了上述问题,可以让一条轨道上的元素同另一条上的对齐。二者的效果对比如图 5.8 所示。

图 5.8 Flexbox 只在一个方向上对齐各元素,而网格则在两个方向上同时对齐

根据 CSS WG 成员 Rachel Andrew 的观点,它们的第二个区别在于,Flexbox 是从内容出发的,而网格则从布局出发的。Flexbox 将一系列元素排布到一行或一列中,无需专门设置元素的尺寸大小,因为尺寸是根据自身内容决定的。

而在网格中,先要定义好布局,然后将各元素放到布局结构中。鉴于每个元素的内容都能影响所在网格轨道的尺寸,这样整个轨道尺寸也都将受其影响,进而波及到轨道内的其他元素大小。

示例页的主区域用网格来定位,是希望其内容能限制在它所在的网格内;而对于页面上的其他元素,如导航菜单,这样的限制则大可不必:元素文字多的也可以适当宽一点,文字少也可以窄一些。此外,它还是一个水平(一维)布局。因此首选 Flexbox 进行布局。接下来用 Flexbox 给这些元素分别设置布局,完成整个页面样式设计。

如图 5.9 所示,顶部导航菜单里的链接是水平对齐的。右下角报价板块的样式也用 Flexbox 进行了处理。加上这些布局和少量的其他样式后,示例页的最终样式就完成了。

图 5.9 示例页面最终效果图

除了整体的布局是用网格实现的(如代码清单 5.4 所示),其余样式都跟第四章一样,这里直接复用。根据以下样式更新示例页。

代码清单 5.5 剩余的页面样式

css 复制代码
.page-heading {
  margin: 0;
}
 
.site-nav {
  display: flex;  /* 用 Flexbox 处理导航菜单 */
  gap: var(--gap-size);
  margin: 0;
  padding: 0.5em;
  background-color: #5f4b44;
  list-style-type: none;
}
 
.site-nav > li > a {
  display: block;
  padding: 0.5em 1em;
  background-color: #cc6b5a;
  color: white;
  text-decoration: none;
}
 
.site-nav > .nav-right {
  margin-inline-start: auto;
}
 
.login-form h3 {
  margin: 0;
  font-size: 0.9em;
  font-weight: bold;
  text-align: right;
  text-transform: uppercase;
}
 
.login-form input:not([type="checkbox"]):not([type="radio"]) {
  display: block;
  width: 100%;
}
 
.login-form button {
  margin-block-start: 1em;
  border: 1px solid #cc6b5a;
  background-color: white;
  padding: 0.5em 1em;
  cursor: pointer;
}
 
.centered {
  text-align: center;
}
 
.cost {
  display: flex;  /* 用 Flexbox 处理价格部分 */
  justify-content: center;
  align-items: center;
  line-height: 0.7;
}
 
.cost-currency {
  font-size: 2rem;
}
.cost-dollars {
  font-size: 4rem;
}
.cost-cents {
  font-size: 1.5rem;
  align-self: flex-start;
}
 
.cta-button {
  display: block;
  background-color: #cc6b5a;
  color: white;
  padding: 0.5em 1em;
  text-decoration: none;
}

当设计要求元素在两个维度上同时对齐时,首选网格布局;若只考虑单一维度上的元素排布问题,则选用 Flexbox 布局。实践中,这通常(并非绝对)意味着网格更适用于整体的页面布局,而 Flexbox 则更适合网格区域内的特定元素布局。网格和 Flexbox 布局用得多了,对于不同场景下该用什么样的布局方式自然就游刃有余了。

注意

网格布局和 Flexbox 布局都能避免元素间发生外边距折叠(margin collapsing)。随着间隙 gap 的设置,通过用户代理引入的外边距可能偶尔会在元素间产生多余的间距。这也是示例样式中好几处将外边距重置为 0 的根本原因。



关于《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 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!

相关推荐
前端爆冲3 分钟前
项目中无用export的检测方案
前端
热爱编程的小曾31 分钟前
sqli-labs靶场 less 8
前端·数据库·less
gongzemin43 分钟前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox1 小时前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
-代号95271 小时前
【JavaScript】十四、轮播图
javascript·css·css3
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
庸俗今天不摸鱼2 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下2 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox2 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞2 小时前
Firefox默认在新标签页打开收藏栏链接
前端·firefox