网格布局中自动放置 | CSS Grid Layout: Auto-placement in CSS Grid Layout
CSS Grid Layout: Auto-placement in CSS Grid Layout
除了能够将项目准确地放置到创建的网格上外, CSS 网格布局规范还包含控制在创建网格时发生的情况以及不放置部分或全部子项的规则。您可以通过在一组项上创建网格, 以最简单的方式看到在操作中自动放置。如果你给项目没有放置信息, 他们将自己放置在网格中, 每个网格单元格中的一个。
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr
grid-gap: 10px;
}
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
默认规则
正如您在上面的示例中所看到的,如果您创建一个网格,那么所有子项都会将它们自己放置到每个网格单元格中。默认流是按行排列项。网格将在第1行的每个单元格中放置一个项。如果已使用grid-template-rows
属性,则网格将继续将项放置在这些行中。如果网格在显式网格中没有足够的行来放置所有新项隐式
行将被创建。
在隐式网格中调整行的大小
默认情况下,默认情况下自动创建的行在隐式网格中是自动大小的。这意味着它们将包含添加到它们中的内容,而不会导致溢出。
但是,可以使用属性控制这些行的大小。grid-auto-rows
.例如,要使所有创建的行都有100像素高,请使用:
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr
grid-gap: 10px;
grid-auto-rows: 100px;
}
您可以在您的值中使用minmax()
(https://developer.mozilla.org/en-US/docs/Web/CSS/minmax)来grid-auto-rows
创建最小大小的行,然后增大以适应内容它更高。
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four
<br>This cell
<br>Has extra
<br>content.
<br>Max is auto
<br> so the row expands.
</div>
<div>Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr
grid-gap: 10px;
grid-auto-rows: minmax(100px, auto
}
下面的列表将创建一个初始的隐式行轨道为100像素和一秒钟200px
。只要将内容添加到隐式网格中,这将继续
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
<div>Eight</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr
grid-gap: 10px;
grid-auto-rows: 100px 200px;
}
按栏自动放置
您也可以要求网格按列自动放置项目。使用grid-auto-flow
具有值的column
属性。在这种情况下,网格将添加您已经定义使用的行中的项目grid-template-rows
。当它填满一行时,它将移动到下一个明确的列上,或者在隐式网格中创建一个新的列轨迹。与隐式行轨道一样,这些列轨道将自动调整大小。你可以通过控制隐含列的大小grid-auto-columns
,这和grid-auto-rows
一样。
在下一个例子中,我创建了一个具有200个像素高度的三行轨道的网格。我按列自动放置,创建的列将是一个300像素的列宽,然后列宽为100像素,直到有足够的列轨道来保存所有的项目。
.wrapper {
display: grid;
grid-template-rows: repeat(3, 200px
grid-gap: 10px;
grid-auto-flow: column;
grid-auto-columns: 300px 100px;
}
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
<div>Eight</div>
</div>
自动放置物品的顺序
网格可以包含项目的混合。某些项目可能在网格上有位置, 但其他项可能是自动放置的。如果您的文档顺序反映了项目在网格上的顺序, 您可能不需要编写 CSS 规则来放置绝对的所有内容, 这样做会很有帮助。该规范包含一个长部分, 详细介绍网格项目的布局算法, 但是对于我们大多数人来说, 我们只需要记住一些简单的规则就可以了。
修改文件顺序
网格将未被赋予网格位置的项目置于规范中描述为 "订单修改的文档顺序" 中。这意味着, 如果您使用的是 "order
" 属性, 则这些物料将由该订单放置, 而不是其 DOM 顺序。否则, 默认情况下, 它们将按照在文档源中输入的顺序保留。
具有展示位置属性的项
网格将做的第一件事是放置任何项目, 有一个位置。在下面的示例中, 我有12网格项目。项目2和项目5已在网格上使用基于线的放置。您可以看到这些项目是如何放置的, 其他项目则自动放置在空格中。自动放置的项目将放置在按 DOM 顺序放置的项目之前, 它们不会从放置在其前面的项的位置开始。
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
<div>Eight</div>
<div>Nine</div>
<div>Ten</div>
<div>Eleven</div>
<div>Twelve</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr
grid-auto-rows: 100px;
grid-gap: 10px;
}
.wrapper div:nth-child(2) {
grid-column: 3;
grid-row: 2 / 4;
}
.wrapper div:nth-child(5) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
处理跨越轨道的物品
您可以使用展示位置属性,同时仍然利用自动展示位置。在下一个示例中,我通过设置奇数项来添加到布局,以跨越行和列的两个轨道。我这样做与grid-column-end
和grid-row-end
属性和设置的这价值span 2
。这意味着该项目的起始行将通过自动放置来设置,并且结束行将跨越两个轨道。
您可以看到它是如何在网格中留下间隙的, 对于自动放置的项目, 如果网格遇到一个不适合跟踪的项目, 它将移动到下一行, 直到找到该项可以容纳的空间。
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
<div>Eight</div>
<div>Nine</div>
<div>Ten</div>
<div>Eleven</div>
<div>Twelve</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr
grid-auto-rows: 100px;
grid-gap: 10px;
}
.wrapper div:nth-child(4n+1) {
grid-column-end: span 2;
grid-row-end: span 2;
background-color: #ffa94d;
}
.wrapper div:nth-child(2) {
grid-column: 3;
grid-row: 2 / 4;
}
.wrapper div:nth-child(5) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
填补缺口
到目前为止, 除了我们特别放置的项目之外, 网格总是在向前推进, 并以 DOM 顺序保存项目。这通常是你想要的, 如果你正在铺设一个表单, 例如你不希望标签和字段变得混乱, 以填补一些空白。然而, 有时, 我们正在铺设的东西没有一个合乎逻辑的顺序,。
为此,请将该属性grid-auto-flow
的值添加dense
到容器中。这是您用来更改流程订单的相同属性column
,所以如果您在列中工作,则可以添加这两个值grid-auto-flow: column dense
。
这样做后, 网格现在将回填的差距, 因为它在网格中移动, 它留下的差距, 因为以前, 但如果它发现一个项目, 将适合在以前的差距, 它将拾起它, 并把它从 DOM 顺序, 把它放在差距。与网格中的任何其他重新排序一样, 这不会更改逻辑顺序。Tab 键顺序例如, 仍将遵循文档顺序。我们将在以后的指南中查看网格布局的潜在可访问性问题, 但是在创建视觉顺序和显示顺序之间的断开时, 您应该小心。
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
<div>Eight</div>
<div>Nine</div>
<div>Ten</div>
<div>Eleven</div>
<div>Twelve</div>
</div>
.wrapper div:nth-child(4n+1) {
grid-column-end: span 2;
grid-row-end: span 2;
background-color: #ffa94d;
}
.wrapper div:nth-child(2) {
grid-column: 3;
grid-row: 2 / 4;
}
.wrapper div:nth-child(5) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr
grid-auto-rows: 100px;
grid-gap: 10px;
grid-auto-flow: dense;
}
匿名网格项
规范中提到了匿名网格项目。如果您的网格容器中有一串文本,而未包含在其他任何元素中,则会创建这些文本。在下面的例子中,我们有三个网格项目,假设你已经设置父一类的grid
来display: grid
。首先是一个匿名的项目,因为它没有封闭的标记,这个项目将总是通过自动放置规则来处理。另外两个是网格项目封闭在一个div,他们可能会自动放置,或者你可以把这些定位方法放到你的网格。
<div class="grid">
I am a string and will become an anonymous item
<div>A grid item</div>
<div>A grid item</div>
</div>
匿名项目总是自动放置的,因为没有办法锁定它们。因此,如果由于某种原因在网格中有一些未包装的文本,请注意它可能会出现在某个意想不到的地方,因为它将根据自动放置规则自动放置。
自动放置用例
当你有一个项目集合时,自动放置是非常有用的.。这可能是没有逻辑顺序的项目,如照片库或产品列表。在这种情况下,您可以选择使用密集填充模式来填充网格中的任何漏洞。在我的图片库例子中,我有一些风景和一些肖像图像。我已经设置了景观图像---landscape
跨两列轨道。然后我用grid-auto-flow: dense
创建一个密集的网格。
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)
grid-gap: 10px;
grid-auto-flow: dense;
list-style: none;
margin: 1em auto;
padding: 0;
max-width: 800px;
}
.wrapper li {
border: 1px solid #ccc;
}
.wrapper li.landscape {
grid-column-end: span 2;
}
.wrapper li img {
display: block;
object-fit: cover;
width: 100%;
height: 100%;
}
<ul class="wrapper">
<li><img src="http://placehold.it/200x300" alt="placeholder"></li>
<li class="landscape"><img src="http://placehold.it/350x200" alt="placeholder"></li>
<li class="landscape"><img src="http://placehold.it/350x200" alt="placeholder"></li>
<li class="landscape"><img src="http://placehold.it/350x200" alt="placeholder"></li>
<li><img src="http://placehold.it/200x300" alt="placeholder"></li>
<li><img src="http://placehold.it/200x300" alt="placeholder"></li>
<li class="landscape"><img src="http://placehold.it/350x200" alt="placeholder"></li>
<li><img src="http://placehold.it/200x300" alt="placeholder"></li>
<li><img src="http://placehold.it/200x300" alt="placeholder"></li>
<li><img src="http://placehold.it/200x300" alt="placeholder"></li>
</ul>
自动布局还可以帮助您布局接口项,这些项目确实有逻辑顺序.。下一个例子中的定义列表就是一个例子。定义列表对于样式来说是一个有趣的挑战,因为它们是平面的,没有任何包装dt
和dd
物品。在我的示例中,我允许自动放置项,但是我有类启动dt
在第1栏中,及dd
在第2栏中,这确保术语在一边,而定义在另一边--不管我们各自有多少个。
<div class="wrapper">
<dl>
<dt>Mammals</dt>
<dd>Cat</dd>
<dd>Dog</dd>
<dd>Mouse</dd>
<dt>Fish</dt>
<dd>Guppy</dd>
<dt>Birds</dt>
<dd>Pied Wagtail</dd>
<dd>Owl</dd>
</dl>
</div>
dl {
display: grid;
grid-template-columns: auto 1fr;
max-width: 300px;
margin: 1em;
line-height: 1.4;
}
dt {
grid-column: 1;
font-weight: bold;
}
dd {
grid-column: 2;
}
自动布局(目前)不能做什么?
有几件事经常成为问题。目前,我们不能像我们的物品一样将目标的其他单元格作为目标。如果您按照关于网格上的命名行的最后一个指南,可能已经想到了一个相关的问题。这将是定义一个规则,说:“自动放置项目对下一行命名为”n“,网格将跳过其他行。有关 CSSWG GitHub存储库的这个问题提出,并欢迎您添加你自己的用例。
您可能会想出自己的用例来自动放置网格布局的任何其他部分。如果你这样做,提出他们的问题或添加到现有的问题,可以解决你的用例。这将有助于使规范的未来版本更好。