去年,我在完成一个研讨会后整理了一篇关于 CSS Grid 布局的有趣事实的文章 关于 CSS 网格布局的一些有趣的事实。今年,我参与了另一个研讨会,并且又学习了一些关于 我们都非常喜欢的布局规范 的激动人心的新事实。
当然,我不会把我的知识藏着掖着。我很乐意再次与您,CSS-Tricks 社区分享我的发现。
理解 `grid` 快捷方式的工作原理
有时候,阅读和理解网格规范(或实际上任何其他规范)的部分内容会非常困难。
例如,我花了相当长的时间才理解如何正确使用 `grid` 快捷方式。规范中指出有效值为
<‘grid-template’> | <‘grid-template-rows’> / [ auto-flow && dense? ] <‘grid-auto-columns’>? | [ auto-flow && dense? ] <‘grid-autwo-rows’>? / <‘grid-template-columns’>
如果您花时间或您习惯阅读规范,您可以理解它。我尝试了几种组合,但都失败了。最终帮助我的是规范中的一句话
请注意,您只能在一个网格声明中指定显式或隐式网格属性。
Rachel Andrew 有一系列文章,文章系列,以 CSS Grid 为例,帮助解释如何阅读规范。
因此,我们可以使用 `grid` 快捷方式指定大量内容,但不能一次性指定所有内容。以下是一些示例。
使用 `grid` 代替 `grid-template`
grid-template
属性是用于在单个声明中设置 `grid-template-columns`、`grid-template-rows` 和 `grid-template-areas` 的简写。我们可以用 `grid` 快捷方式做同样的事情,它更简洁一些。
grid: "one one" 200px
"two four"
"three four"
/ 1fr 2fr;
/* shorthand for: */
/*
grid-template-areas: "one one" "two four" "three four";
grid-template-rows: 200px;
grid-template-columns: 1fr 2fr;
*/
此快捷方式创建了三行两列,并有四个命名的网格区域。第一行的高度为 `200px`,而第二行和第三行的高度为 `auto`。第一列宽度为 `1fr`,第二列宽度为 `2fr`。
查看代码笔 网格快捷方式 - 区域、显式行和列,由 Manuel Matuzovic (@matuzo) 在 CodePen 上创建。
想了解更多关于显式网格和隐式网格的区别?查看 这篇我撰写关于该主题的文章,发布在 CSS-Tricks 上。
如果不需要,我们不必指定区域。我们可以仅使用 `grid` 快捷方式来定义显式行和列。以下两个代码片段本质上是做同样的事情
grid-template-rows: 100px 300px;
grid-template-columns: 3fr 1fr;
grid: 100px 300px / 3fr 1fr;
处理隐式行和列
可以使用 `grid` 快捷方式指定 `grid-auto-flow`,但它并不完全按照我们的预期工作。我们不能仅仅在声明中添加 `row` 或 `column` 关键字。相反,我们必须在斜杠的正确位置使用 `auto-flow` 关键字。
如果它位于斜杠左侧,则快捷方式将 `grid-auto-flow` 设置为 `row` 并创建显式列。
grid: auto-flow / 200px 1fr;
/* shorthand for: */
/*
grid-auto-flow: row;
grid-template-columns: 200px 1fr;
*/
如果它位于斜杠右侧,则快捷方式将 `grid-auto-flow` 设置为 `column` 并创建显式行。
grid: 100px 300px / auto-flow;
/* shorthand for: */
/*
grid-template-rows: 100px 300px;
grid-auto-flow: column;
*/
我们还可以与 `auto-flow` 关键字一起设置隐式轨道的大小,这分别将 `grid-auto-rows` 或 `grid-auto-columns` 设置为指定的值。
grid: 100px 300px / auto-flow 200px;
/* shorthand for: */
/*
grid-template-rows: 100px 300px;
grid-auto-flow: column;
grid-auto-columns: 200px;
*/
查看代码笔 网格快捷方式 - 显式行和隐式列,由 Manuel Matuzovic (@matuzo) 在 CodePen 上创建。
Edge 中的特性查询
使用 特性查询 检查 CSS Grid 的支持效果很好,因为所有支持 Grid 的浏览器也都理解特性查询。这意味着我们可以检查浏览器是否支持旧规范或新规范,或者两者都支持。两者都支持?从 Edge 16 开始,Edge 不仅支持新规范,还支持旧规范。
因此,如果您想区分支持新规范的 Edge 版本和不支持的版本,您必须这样编写查询
/* Edge 16 and higher */
@supports (display: -ms-grid) and (display: grid) {
div {
width: auto;
}
}
/* Edge 15 and lower */
@supports (display: -ms-grid) and (not (display: grid)) {
div {
margin: 0
}
}
这里有一个方便的小演示,显示了在您打开它的浏览器中触发了哪个特性查询。
查看代码笔 display: grid 支持测试,由 Manuel Matuzovic (@matuzo) 在 CodePen 上创建。
顺便说一下,您不应该过度(误用)特性查询进行浏览器嗅探,因为 浏览器检测是错误的。
指定每列的精确项目数量
网格非常适合页面布局,但也非常适合组件级别。我最喜欢的示例之一是能够在多列组件中指定每列的精确项目数量。
假设我们有一个包含 11 个项目的列表,并且我们希望在每四个项目后添加一个新列。在对父元素设置 `display: grid` 后,我们要做的第一件事是更改网格自动放置算法的工作方式。默认情况下,它会依次填充每行,并在需要时添加新行。如果我们将 `grid-auto-flow` 设置为 `column`,网格将改为依次填充每列,这正是我们想要的。我们必须做的最后一件事是指定每列的项目数量。这可以通过使用 `grid-template-rows` 属性定义所需的显式行数来实现。我们可以显式设置每行的高度,或者使用 `auto` 关键字使它们与内容一样大。
ul {
display: grid;
grid-template-rows: auto auto auto auto;
/* or shorter and easier to read: */
/* grid-template-rows: repeat(4, auto); */
grid-auto-flow: column;
}
如果我们必须将每列的项目数量更改为 5,我们只需在轨道列表中添加另一个轨道,或者使用 重复表示法,只需将第一个参数更改为所需的值 `(grid-template-rows: repeat(5, auto))`。
查看代码笔 每列限制的项目数量,由 Manuel Matuzovic (@matuzo) 在 CodePen 上创建。
使用 CSS 网格创建粘性页脚
有很多方法可以用 CSS 创建粘性页脚 创建粘性页脚的方法。其中一些方法很笨拙而且复杂,但使用网格就很直接了。
假设我们有一个*经典*的页眉、主要内容和页脚页面结构。
<body>
<header>HEADER</header>
<main>MAIN</main>
<footer>FOOTER</footer>
</body>
首先,我们将 `html` 和 `body` 的 `height` 设置为视窗的至少 `100%`,以确保页面始终使用完整的垂直空间。然后,我们将 `grid-template-rows` 应用于将 `body` 分割成三行。第一行(`header`)和最后一行(`footer`)可以具有我们想要的任何大小。如果我们希望它们始终与内容一样大,我们只需将高度设置为 `auto`。中间的行(`main`)应该始终填充剩余的空间。我们不必计算高度,因为我们可以使用 分数单位 来实现这一点。
html {
height: 100%;
}
body {
min-height: 100%;
display: grid;
grid-template-rows: auto 1fr auto;
}
因此,主要内容会增长,页脚会相应地调整并保持在视窗的底部。
查看代码笔 CSS 网格布局粘性页脚,由 Manuel Matuzovic (@matuzo) 在 CodePen 上创建。
网格项目的自动最小尺寸
最近,Florian 在 Twitter 上发帖说他想知道为什么 在网格项目中截断单行文本如此复杂。他的示例完美地说明了网格项目的一个有趣事实。
初始情况是一个三列网格,每个网格项目中都包含一个段落。
<div class="grid">
<div class="item">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo ipsum exercitationem voluptate, autem veritatis enim soluta beatae odio accusamus molestiae, perspiciatis sunt maiores quam. Deserunt, aliquid inventore. Ullam, fugit dicta.
</p>
</div>
</div>
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 20px;
}
每段文本应仅为单行,如果段落比其父级项目长,则在行末显示省略号。Florian 通过将 white-space
设置为 nowrap
来解决这个问题,这会强制使用单行,隐藏 overflow
并将 text-overflow
设置为 ellipsis
。
p {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
这在块级元素上可以完美地工作,但在网格示例中,列会扩展到单行段落的宽度。
查看 Manuel Matuzovic 在 CodePen 上创建的 网格项目的自动最小尺寸 演示。
总的来说,这是因为网格项目不能小于其子元素。网格项目(或弹性项目)的默认 min-width
设置为 auto
,根据规范...
…对溢出可见且跨越至少一条最小轨道大小函数为 auto 的轨道,在指定的轴上应用自动最小尺寸。
这使得网格和弹性项目更灵活,但有时不希望内容能够拉伸其父级项目的宽度。为了避免这种情况,我们可以将网格项目的 overflow
属性更改为除 visible
之外的任何其他值,或者将 min-width
设置为 0
。
查看 Manuel Matuzovic 在 CodePen 上创建的 CSS 网格中截断文本 演示。
在网格规范中详细了解网格项目的自动最小尺寸。
总结
希望这些最新的收获能帮助你像我一样更轻松地编写和使用网格。这个新规范中有很多细节,但随着使用次数的增多,它会变得更加有趣和易于理解。
很酷。它表明
grid
本身是两部分的简写:行/列。我认为这解释了很多东西,但我们不是为了优化而牺牲了可读性吗?我认为我可以在个人项目中使用它,但在团队中,我宁愿使用完整的符号。否则,很棒的文章。我相当肯定我不会在生产环境中使用它。尽管如此,我认为它值得一些解释。:)