该帖子的编辑日期为 以便在重叠网格项目的示例中更好地描述项目放置。
当观察人们逐渐熟悉CSS Grid时,我注意到一些问题比其他人更容易吸引人们,或者在构建布局时面临更多挑战。 本简短的系列文章将深入探讨这些常见问题,旨在更好地理解Grid,以便您可以预期布局问题,并在出现问题时更轻松地对其进行调试。
意外的隐式轨迹
我见过的人们最大的难题是无意中创建了额外的网格轨迹,这可能会使整个布局混乱。 这些额外的轨道称为隐式轨道,它们是通过将项目放置在显式网格边界之外而创建的。 为了充分利用Grid,最好了解显式和隐式网格的概念以及它们之间的关系。
显式网格
显式网格是使用grid-template-rows
和grid-template-columns
属性定义的(如果需要,可以使用简写的grid-template
):
.grid{
display: grid ;
grid-template-rows:repeat( 4 , 150px );
grid-template-columns:repeat( 4 , 1fr );
}
在这里,我们定义了一个具有四行四列的网格,并且可以知道我们的网格将至少具有四行四列。 即使我们没有放置任何网格子对象,以使我们的网格完全是空的,它仍然会占用上面定义的四行四列的空间。
如果我们对grid-template-rows
属性使用repeat(4, auto)
,那么我们的网格行都将具有高度auto
–因此,如果我们没有网格子级,那么我们的行仍将存在,它们将折叠为零高度,没有任何内容可填充它们。 如果我们添加行间隙(例如row-gap: 40px
),那么row-gap: 40px
的合并高度将构成网格的高度–因此,如果没有任何内容,它可能看起来像是一个较大的边距或填充值,破坏了您的布局!
什么是隐式轨道?
隐式轨道是仅通过放置项目创建的轨道。 Grid中的这种行为是有意的,非常有用。 例如,如果您有一个四列的网格,我们要用不确定的项目数来填充(例如,新闻提要。如果我们不知道项目数,那么我们将不知道需要多少行默认情况下,网格项放置在下一个可用的网格单元中,我们可以简单地省略grid-template-rows
属性,并允许Grid的自动放置为内容创建正确的行数。
(旁注:我在这里假设网格使用默认的grid-auto-flow: row
。如果将其更改为grid-auto-flow: column
,则将在行轴上创建隐式轨道。)
.grid{
display: grid ;
grid-template-columns:repeat( 4 , 1fr );
}
![在两行上布置了七个网格项目 Seven grid items laid out over two rows](https://i-blog.csdnimg.cn/blog_migrate/a90c47096677c9ce2d0c6f8c607b7481.png)
我们可以使用grid-auto-rows
和grid-auto-columns
控制隐式轨道的行为。
.grid{
display: grid ;
grid-template-rows:repeat( 4 , 150px );
grid-template-columns:repeat( 4 , 1fr );
grid-auto-rows: 150px ;
}
上面的代码除了定义四个显式的列和行轨迹之外,还指示Grid任何创建的隐式行轨迹应具有150px的固定高度。 此属性是可选的,如果没有此属性,任何隐式轨道的默认大小将为auto
。
放置物品
要将项目放置在我们刚刚创建的网格上,我们可以执行以下操作:
.item{
grid-column: 1 / 2 ;
grid-row: 3 / 5 ;
}
我们正在使用开始行和结束行将网格项放置在网格的左下方。
![橙色网格项目放置在网格的左下方 Orange grid item placed at the bottom left of the grid](https://i-blog.csdnimg.cn/blog_migrate/6a62b266d9765a161761e99279863d61.png)
这不会造成任何问题,因为我们通过网格线号显式放置项目。 我们知道网格有四行四列(因此在任一方向上有五条网格线),因此我们不太可能无意间无意地使用了更高的行号并偶然地创建了隐式轨迹。
另外,我们可以使用span关键字代替开始或结束行:
.item{
grid-column: 1 / 2 ;
grid-row: 3 / span 2 ;
}
我喜欢使用span
进行网格放置–当您知道某个项目需要跨一定数量的网格轨迹而不是在特定的行结束时,这通常会很有用–但是这意味着您有时可能会失去对所放置的网格线的跟踪一个项目。
在这里,我们使用span
代替了grid-row-end
线。 如果我们将跨度值更改为3而不是2,这将导致该项目跨度超过可用行的行径–哇! 我们创建了一个隐式轨道!
![橙色网格项目放置在网格的左下方 Orange grid item placed at the bottom left of the grid](https://i-blog.csdnimg.cn/blog_migrate/8361137bd6b1d6e84cf29417c33477d7.png)
有时会出现此问题的一个地方是当您希望网格项目相互重叠时。 没有显式放置的项目将放置到下一个可用的网格单元中,如果没有可用的网格单元,则将创建隐式轨道,而不是将项目堆叠在一起。 这种行为非常有用,因为它意味着我们不必总是显式放置项目,但是在这种情况下,它对我们并不是特别有用!
我的一个朋友正在使用Grid定位两个元素,一个元素位于另一个元素的顶部,但偏移了一行:
![具有两个重叠项的网格布局 A grid layout with two overlapping items](https://i-blog.csdnimg.cn/blog_migrate/827d40fee22c549b39ba37699c28e513.png)
这是用于创建布局的代码:
.grid{
display: grid ;
grid-template-columns:repeat( 4 , 1fr );
grid-template-rows:repeat( 3 , 200px );
}
.item:first-child{
grid-column: span 4 ;
grid-row: 1 / span 2 ;
}
.item:nth-child(2){
grid-column: span 4 ;
grid-row: 2 / span 2 ;
}
而不是所需的布局,我们得到这样的:
![网格布局,其中第二项推到右侧 A grid layout with the second item pushed to the right](https://i-blog.csdnimg.cn/blog_migrate/f8c8be2ef6ef5320e8791ff254f0c5a7.png)
第二项怎么了? 您能在这里发现问题吗? 两项都使用span关键字作为grid-column
值。 第一项将正确放置,因为它将自动放置在跨度为4的第一个可用单元格中。第二项没有开始或结束行,因此浏览器需要解决此问题,方法是:生成隐式列轨道。
如果第二个项目只有一个span值,并且行轴上没有起始线,则它将包装到下一行,因为该项目仍将参与网格的流动。 这不是我们想要的布局,但可能会减少一些困惑! 但是在上面的代码中,浏览器不知道我们要将项目放置在哪一列。它通过将项目从列轴的第5行开始放置并生成四个隐式轨道来解决此问题。
因为我们没有使用grid-auto-columns
为隐式轨道定义大小,所以它们的默认大小为auto
。 如果网格项目没有内容,那么这些轨道将折叠为0的宽度,从而使我们的项目不可见。 我们的网格项目包含一些文本,因此这些隐式轨道将自动调整大小以适应此情况。
如果我们的column-gap
值为20px
,则将看到两个列间距的宽度被添加到了网格中,尽管轨迹本身的宽度为0。
这里的解决方案是将两个项目显式地放置在起始值和结束值处:
.item:first-child{
grid-column: 1 / span 4 ;
grid-row: 1 / span 2 ;
}
.item:nth-child(2){
grid-column: 1 / span 4 ;
grid-row: 2 / span 2 ;
}
播放下面的演示,探索“破坏”布局的不同方法:
防止布局中断
那么,如何最好地避免隐式轨道出现问题呢? 一种方法是了解Grid如何在后台计算我们的布局。
了解网格项目放置算法
这听起来比实际要可怕! 网格项目放置算法是解决网格项目放置的顺序。 首先明确定位的网格项目,然后是具有明确行位置的项目,然后浏览器确定隐式网格中的列,并相应地放置所有自动放置的项目(没有明确位置的项目)。 这是假设grid-auto-flow
属性值是row
(默认值)。 牢记这一点可以帮助您理解为什么在一个轴上而不是在另一个轴上创建隐式轨迹(如果这与您的期望相反)。
我还为您提供了一些放置物品的技巧,以帮助您避免意外将物品从明确的网格中推出...
命名网格线
一种使我对网格放置更加有心的方法是命名网格线。 假设我们要放置的项目是一张图片。 我们可以这样做:
.grid{
display: grid ;
grid-template-rows:
repeat( 2 , 150px ) [image-start] repeat( 2 , 150px )
[image-end] ;
grid-template-columns: [image-start] repeat( 3 , 1fr ) [image-end] 1fr ;
grid-auto-rows: 150px ;
}
使用-start和-end作为行名的后缀会创建一个网格区域,这使得放置图像非常简单:
.image{
grid-area: image ;
}
您还可以使用grid-template-areas
属性执行类似的操作,这对许多人来说更直观–请记住,如果需要重叠的网格项,则该操作将无效。
按端线放置
有时按结束行号(而不是起始行号)放置可以避免产生意外的隐式轨迹的问题。 以上面的示例为例,也许我们知道我们希望图像跨越三个网格轨迹,所以我们将span关键字用作grid-column-end
值。 但是,最好使用span作为grid-column-start
值并将其显式放置在其结束行上:
.image{
/* The image will end at line 4 on the column axis: */
grid-column: span 3 / 4 ;
}
如果我们有一个非常大的网格,这可能会有所帮助。 想象一下,我们的网格有20列而不是4列,我们可能知道它需要放置在离末端一排的位置,但是我们不想每次都必须计算起始行,这很烦人并容易出错!
负网格线
我发现一种非常有用的技术(以及我之前写过的东西)是使用负行号放置网格项。 负行号代表网格的反行。 因此,在具有四个轨道的网格中(该网格具有五个网格线),线-1相当于线5,线-2相当于线4,依此类推。
同样,在使用大型网格时,这非常方便。 如果我们知道并且项目需要与网格的末端对齐,那么我们可以简单地使用网格线-1,而不必记住最后一行是第21行。
使用开发工具进行调试
我彻底推荐使用Firefox开发工具来检查和调试CSS Grid问题。 网格检查器允许您打开行号,因此,即使隐式轨道的大小已缩小到零,您仍然可以看到它们已经创建。 (检查员还会向您显示负行号-非常方便!)
结论
我希望本文能在使用CSS Grid的过程中使示例性轨道与显式轨道的神秘化,并为您提供一些有价值的知识来帮助您调试损坏的布局。 在即将推出的Debugging CSS Grid系列中查找更多文章。
翻译自: https://css-irl.info/debugging-css-grid-part-1-understanding-implicit-tracks/