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

相关推荐
活宝小娜1 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点1 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow1 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o1 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic2 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā2 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年3 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder4 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727574 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
SoaringHeart4 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter