MDN’s new design is in Beta! A sneak peek: https://blog.mozilla.org/opendesign/mdns-new-design-beta/

网格布局的基本概念

这篇翻译不完整。请帮忙从英语翻译这篇文章

CSS网格布局引入了二维网格布局系统,可用于布局页面主要的区域布局或小型组件。本文介绍了CSS网格布局 与 CSS网格布局规范 Level 1 中的新术语。这篇简介中所展示的每种特性,随后将在本指南的其余部分中有更详细地介绍。

什么是网格?

网格是一组相交的水平线和垂直线,它定义了网格的列和行。我们可以将网格元素放置在与这些行和列相关的位置上。CSS网格布局具有以下特点:

固定或弹性的轨道尺寸

你可以使用固定的轨道尺寸创建网格,比如使用像素单位。你也可以使用弹性尺寸比如百分比或者专门为此目的创建的新单位 fr.

定位项目

你可以使用行号、行名或者标定一个网格区域来精确定位项目。网格同时还使用一种算法来控制未给出明确网格位置的项目。

创建额外的轨道来保存内容

可以使用网格布局定义一个显式网格,但该规范还涉及在声明网格外添加的内容,如需要添加额外的行和列。包括添加“尽可能多的列,以适应容器”的功能。

对齐控制

网格包含对齐特征,以便我们可以控制一旦放置到网格区域中的物体对齐,以及整个网格如何对齐。

控制重叠内容

多个项目可以放置在网格单元格中,或者区域可以部分地彼此重叠。然后可以用这种分层进行控制("z-index")}}.

Grid是一个强大的规范,当与CSS的其他部分(如flexbox)结合使用时,可以帮助您创建以前不可能在CSS中构建的布局。这一切都是通过在网格容器上创建一个网格来开始的。

网格容器

我们通过在元素上声明 display:griddisplay:inline-grid 来创建一个网格容器。一旦我们这样做,这个元素的所有直系子元素将成为网格项目。

在这个例子中,我有一个类名为 wrapper 的作为容器的 div 元素,它内部有五个子元素。

<div class="wrapper">
   <div>One</div>
   <div>Two</div>
   <div>Three</div>
   <div>Four</div>
   <div>Five</div>
</div>

我将 .wrapper 作为一个网格容器。

.wrapper {
  display: grid;
}

所有直系子元素现在都是网格项目了。在网络浏览器中,当网格为项目创建单列列网格时,在将项目显示为网格之前,您将看不到任何差异。在这一点上,你可能会发现在Firefox Developer Edition中有用,该开发人员版具有Grid Inspector作为开发工具的一部分。如果你在Firefox中查看此示例并检查网格,则会在值网格旁边看到一个小图标。单击此处,此元素上的网格将覆盖在浏览器窗口中。

Using the Grid Highlighter in DevTools to view a grid

当你学习并且使用CSS网格布局时,这个工具能让你更好地了解到你的网格在视觉上发生了哪些变化。

如果我们想让这个例子更加“网格化”,我们需要使用网格轨道。

网格轨道

我们通过定义网格容器的grid-template-columns和grid-template-rows属性来定义网格中的行和列。这些属性定义了网格的轨道。一个网格轨道就是网格中任意两条线之间的空间。在下图中你可以看到一个高亮的轨道-网格的第一个行轨道。

我可以通过添加grid-template-columns属性添加到我们前面的例子,然后定义列轨迹的大小。

我现在创建了一个网格,三个200像素宽栏轨道。子项目将在每个网格单元中的网格上展开。

<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: 200px 200px 200px;
}

fr单位

轨道可以使用任何长度单位进行定义。 Grid还引入了一个额外的长度单位来帮助我们创建灵活的网格轨道。新的fr单位代表网格容器中可用空间的一小部分。下一个网格定义将创建三个相等宽度的轨道,根据可用空间增长和收缩。

<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: 1fr 1fr 1fr;
}

在下面的这个例子中,我们创建一个定义一个2fr跟踪两1fr轨道。可用空间分割为四。两个部分给出了第一个轨道和一个部分到下两个。

.wrapper {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
}

在最终的例子中,我们将绝对尺寸的轨道与分数单位进行混合。第一个轨道是500像素,因此这个固定宽度被从可用空间中取走。剩下的空间被分为三个,并且与两个柔性轨道成比例地分配。

.wrapper {
  display: grid;
  grid-template-columns: 500px 1fr 2fr;
}

具有repeat()符号表示轨道列表

具有许多轨道的大网格可以使用repeat()符号重复轨道列表的所有或部分。例如网格定义:

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

也可以写成:

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

Repeat符号可以被用作轨道清单中的一部分。在下一个例子中我已经创建了一个初始轨道为20像素的网格,接着repeat标记6个1fr的轨道,然后再添加一个20像素的轨道。

.wrapper {
  display: grid;
  grid-template-columns: 20px repeat(6, 1fr) 20px;
}

Repeat符号可以占据一个轨道的清单,因此你可以用它来创建一个重复模式的轨道。在下一个例子中,网格将会包括10个轨道,1个1fr的轨道后面跟着1个2fr的轨道,重复5次。

.wrapper {
  display: grid;
  grid-template-columns: repeat(5, 1fr 2fr);
}

隐式和显式网格

当创建我们自己的网格例子的时候,我们用grid-template-columns属性定义自己的列轨道,但是却让网格按所需的内容创建行,这些行会被创建在隐式网格中。显式网格包含了你在grid-template-columns和grid-template-rows属性中定义的行和列,如果你在网格定义之外又放了一些东西,或者因为内容的数量而需要的更多网格轨道的时候,网格将会在隐式网格中创建行和列。这些轨道将被自动初始化为默认大小,所以会根据它里面的内容改变尺寸。

你也可以在隐式网格中用grid-auto-rows和grid-auto-columns属性来定义一个设置大小尺寸的轨道。

在下面的例子中我们用grid-auto-rows属性来确保在隐式网格中创建200像素高的轨道。

<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-auto-rows: 200px;
}

轨道大小和minmax()

在设置一个显式的网格或者定义自动创建的行和列的大小的时候,我们也许想给网格一个最小的尺寸,但要确保他们能扩大到容纳他里面添加的内容。举个例子,我想让我的行的高度永远不会缩小到100像素以下,但是如果我的内容延伸到300像素高了我想让我的行高也延伸到这个高度。

网格针对这个问题用"minmax", "minmax()"方法有一个解决方案。在下一个例子中我用minmax()作为grid-auto-rows的值。自动创建的行高将会是最小100像素,最大为auto。用auto意味着行的尺寸将会根据内容的大小来自动变换,并且会根据本行中最高的网格来延伸出一个足够容纳他的空间。

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto);
}
<div class="wrapper">
   <div>One</div>
   <div>Two
   <p>I have some more content in.</p>

<p>This makes me taller than 100 pixels.</p>
</div>
   <div>Three</div>
   <div>Four</div>
   <div>Five</div>
</div>

网格线

应该注意的是,当我们定义网格时,我们定义的是网格轨道,而不是网格线。Grid 会为我们创建编号的网格线来让我们来定位每一个网格项目. 例如下面这个三列两行的网格中,就拥有四条纵向的网格线。

Diagram showing numbered grid lines.

网格线的编号顺序取决于文章的书写模式。在从左至右书写的语言中,编号为 1 的网格线位于最左边。在从右至左书写的语言中,编号为 1 的网格线位于最右边。 网格线也可以被命名,我们将在稍后的教程中看到如何完成这一操作。

Positioning items against lines

We will be exploring line based placement in full detail in a later article, the following example demonstrates doing this in a simple way. When placing an item we target the line – rather than the track.

In the following example I am placing the first two items on our three column track grid, using the grid-column-start, grid-column-end, grid-row-start and grid-row-end properties. Working from left to right, the first item is placed against column line 1, and spans to column line 4, which in our case is the far right line on the grid. It begins at row line 1 and ends at row line 3, therefore spanning two row tracks.

The second item starts on grid column line 1, and spans one track. This is the default so I do not need to specify the end line. It also spans two row tracks from row line 3 to row line 5. The other items will place themselves into empty spaces on the grid.

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
   <div class="box4">Four</div>
   <div class="box5">Five</div>
</div>
.wrapper { 
    display: grid; 
    grid-template-columns: repeat(3, 1fr); 
    grid-auto-rows: 100px; 
} 
.box1 { 
    grid-column-start: 1; 
    grid-column-end: 4; 
    grid-row-start: 1; 
    grid-row-end: 3; 
} 
.box2 { 
    grid-column-start: 1; 
    grid-row-start: 3; 
    grid-row-end: 5; 
}

Don't forget that you can use the Grid Inspector in Firefox Developer Tools to see how the items are positioned against the lines of the grid.

Grid Cells

A grid cell is the smallest unit on a grid, conceptually it is like a table cell. As we saw in our earlier examples, once a grid is defined on a parent the child items will lay themselves out once in each cell of the defined grid. In the below image I have highlighted the first cell of the grid.

The first cell of the grid highlighted

Grid areas

Items can span one or more cells both by row or by column, and this creates a grid area. Grid areas have to be rectangular – it isn’t possible to create an L-shaped area for example. The highlighted grid area spans two row and two column tracks.

A grid area

Gutters

Gutters or alleys between grid cells can be created using the grid-column-gap and grid-row-gap properties, or the shorthand grid-gap. In the below example I am creating a 10-pixel gap between columns and a 1em gap between rows.

.wrapper {
   display: grid;
   grid-template-columns: repeat(3, 1fr);
   grid-column-gap: 10px;
   grid-row-gap: 1em;
}
<div class="wrapper">
   <div>One</div>
   <div>Two</div>
   <div>Three</div>
   <div>Four</div>
   <div>Five</div>
</div>

Any space used by gaps will be accounted for before space is assigned to flexible length fr tracks, and gaps act for sizing purposes like a regular grid track, however you cannot place anything into a gap. In terms of line-based positioning, the gap acts like a fat line.

Nesting grids

A grid item can become a grid container. In the following example I have the three-column grid created earlier, with our two positioned items. In this case the first item has some sub-items. As these items are not direct children of the grid they do not participate in grid layout and so display in normal document flow.

<div class="wrapper">
   <div class="box box1">
       <div class="nested">a</div>
       <div class="nested">b</div>
        <div class="nested">c</div>
    </div>
    <div class="box box2">Two</div>
    <div class="box box3">Three</div>
    <div class="box box4">Four</div>
    <div class="box box5">Five</div>
</div>

Nested grid in flow

If I set box1 to display: grid I can give it a track definition and it too will become a grid, the items then lay out on this new grid.

.box1 {
   grid-column-start: 1;
   grid-column-end: 4;
   grid-row-start: 1;
   grid-row-end: 3;
   display: grid;
   grid-template-columns: repeat(3, 1fr);
}

In this case the nested grid has no relationship to the parent. As you can see in the example it has not inherited the grid-gap of the parent and the lines in the nested grid do not align to the lines in the parent grid.

Subgrid

In the level 1 grid specification there is a feature called subgrid which would let us create nested grids that use the track definition of the parent grid.

Subgrids are not yet implemented in any browsers, and the specification is subject to change.

In the current specification, we would edit the above nested grid example to use display: subgrid rather than display: grid, then remove the track definition. The nested grid will use the parent grid tracks to lay out items.

It should be noted that the nested grid is in both dimensions—rows and columns. There is no concept of the implicit grid working with subgrids. This means you need to ensure that the parent grid has enough row and column tracks for all the subitems.

.box1 {
   grid-column-start: 1;
   grid-column-end: 4;
   grid-row-start: 1;
   grid-row-end: 3;
   display: subgrid;
}

Layering items with z-index

Grid items can occupy the same cell. If we return to our example with items positioned by line number, we can change this to make two items overlap.

<div class="wrapper">
   <div class="box box1">One</div>
   <div class="box box2">Two</div>
   <div class="box box3">Three</div>
   <div class="box box4">Four</div>
   <div class="box box5">Five</div>
</div>
.wrapper {
   display: grid;
   grid-template-columns: repeat(3, 1fr);
   grid-auto-rows: 100px;
}
.box1 {
   grid-column-start: 1;
   grid-column-end: 4;
   grid-row-start: 1;
   grid-row-end: 3;
}
.box2 {
   grid-column-start: 1;
   grid-row-start: 2;
   grid-row-end: 4;
}

The item box2 is now overlapping box1, it displays on top as it comes later in the source order.

Controlling the order

We can control the order in which items stack up by using the z-index property - just as with positioned items. If we give box2 a lower z-index than box1 it will display below box1 in the stack.

.wrapper {
   display: grid;
   grid-template-columns: repeat(3, 1fr);
   grid-auto-rows: 100px;
}
.box1 {
   grid-column-start: 1;
   grid-column-end: 4;
   grid-row-start: 1;
   grid-row-end: 3;
   z-index: 2;
}
.box2 {
   grid-column-start: 1;
   grid-row-start: 2;
   grid-row-end: 4;
   z-index: 1;
}

下一个步骤

In this article we have had a very quick look through the Grid Layout Specification. Have a play with the code examples, and then move onto the next part of this guide where we will really start to dig into the detail of CSS Grid Layout.

文档标签和贡献者

标签: 
 此页面的贡献者: lipd, EzioW, 1986slayer
 最后编辑者: lipd,