首页 > 解决方案 > CSS 网格:自动放置算法的工作原理

问题描述

我正在阅读 MDN文章中关于grid-auto-flow中提供的示例,以了解自动放置算法在 CSS 网格中的工作原理。

以下是示例的定义方式(您可以在此处更改选择选项以更改grid-auto-flow属性的值):

function changeGridAutoFlow() {
  var grid = document.getElementById("grid");
  var direction = document.getElementById("direction");
  var dense = document.getElementById("dense");
  var gridAutoFlow = direction.value === "row" ? "row" : "column";

  if (dense.checked) {
    gridAutoFlow += " dense";
  }

  grid.style.gridAutoFlow = gridAutoFlow;
}
#grid {
  height: 200px;
  width: 200px;
  display: grid;
  grid-gap: 10px;
  grid-template: repeat(4, 1fr) / repeat(2, 1fr);
  grid-auto-flow: column;
  /* or 'row', 'row dense', 'column dense' */
}

#item1 {
  background-color: lime;
  grid-row-start: 3;
}

#item2 {
  background-color: yellow;
}

#item3 {
  background-color: blue;
}

#item4 {
  grid-column-start: 2;
  background-color: red;
}

#item5 {
  background-color: aqua;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <link href="/static/build/styles/samples.37902ba3b7fe.css" rel="stylesheet" type="text/css" />
  <title>grid-auto-flow - Setting_grid_auto-placement - code sample</title>
</head>

<body>

  <div id="grid">
    <div id="item1"></div>
    <div id="item2"></div>
    <div id="item3"></div>
    <div id="item4"></div>
    <div id="item5"></div>
  </div>
  <select id="direction" onchange="changeGridAutoFlow()">
    <option value="column">column</option>
    <option value="row">row</option>
  </select>
  <input id="dense" type="checkbox" onchange="changeGridAutoFlow()">
  <label for="dense">dense</label>

</body>

</html>

现在据我从 MDN 的另一篇文章中了解到,CSS 网格按以下顺序放置项目:

  1. 显式放置:首先放置所有已定位的项目(items1 和 4)
  2. 隐式或自动放置:将所有其他项目放置在网格中定义的订单值(如果有)中。如果未定义顺序,请按照它们在文档源中出现的顺序放置它们。

现在我有两个主要问题关于它在上面的例子中是如何工作的:

  1. 如果我们首先放置已定位的项目,那么在选项设置为row的情况下,为什么不将项目 4(红色)显式放置在第一行和第二列?为什么隐式放置的 Blue 在第二列中放置在它之前?Also, this behavior is seemingly correct when option set to column
  2. 为什么在行值的情况下自动放置的工作方式不同。在选项的情况下,我们从填充列开始,那么为什么第一个自动放置的项目(item2 黄色)不能占据 row1、column1 位置的空单元格(就像在 option: row的情况下一样)

标签: htmlcsscss-grid

解决方案


如果我们首先放置已定位的项目,那么在选项设置为行的情况下,为什么不将项目 4(红色)显式放置在第一行和第二列?为什么隐式放置的 Blue 在第二列中放置在它之前?Also, this behavior is seemingly correct when option set to column

为此,您需要参考规范和完整的放置算法

  1. 生成匿名网格项
  2. 定位任何不是自动定位的东西。
  3. 处理锁定到给定行的项目。
  4. 确定隐式网格中的列。
  5. 定位剩余的网格项目。

诀窍是您认为您的元素将被放置在步骤 (1) 中,但没有。您的元素只有一个显式规则,另一个是自动的,因此它算作自动定位元素。

如果我们遵循规则,我们在步骤 (1) 中没有要定位的元素。我们在步骤 (2) 中有一个元素要定位,#item1因为它被锁定到给定的行然后所有其他元素都放置在步骤 (4) 中,文档顺序将定义放置:

对于前面步骤中没有定位的每个网格项,按照order-modified 文档 order

您没有使用该order属性,因此文档顺序将作为参考。

值得注意的是,这同样适用于column流程,但结果更直观,因为我们首先放置#item4(列锁定)然后考虑我们放置的文档顺序#item1(不是因为这个有grid-row-start: 3;


为什么在行和列值的情况下自动放置的工作方式不同。在选项列的情况下,我们从填充列开始,那么为什么第一个自动放置的项目(项目 2 黄色)不能占据 row1、column1 位置的空单元格(就像在 option: row 的情况下一样)

我认为上面的解释也涵盖了这一点。您需要遵循在两种情况下表现不同的算法:

为了清楚起见,该算法是在假设 grid-auto-flow 已指定行的情况下编写的。如果它改为设置为列,则在此算法中交换所有提及的行和列、内联和块等。


推荐阅读