将深度嵌套的元素放置在更高级别的网格容器中

Position deeply nested elements in a higher level grid container

所有关于 CSS 网格的指南似乎暗示了一种结构,其中位于网格中的元素是网格元素本身的直接子元素:

<div class="wrapper">
  <div>A</div>
  <div>B</div>
</div>

其中 .wrapper 具有 display: gridgrid 属性的定义。

如果我想将作为网格“孙子”的元素放置在网格本身(而不是依赖于其父元素)上,这是否有意义?

<div class="wrapper">
  <div>A</div>
  <div>
    <div>B</div>
    <div>C</div>
  </div>
</div>

我想将 ABC 分别放在网格的各自行中;这甚至有意义吗?

display: subgrid

来自CSS Grid Level 2 draft spec:

2. Grid Containers

Subgrids provide the ability to pass grid parameters down through nested elements, and content-based sizing information back up to their parent grid.

If the element is a grid item (i.e. it is in-flow and its parent is a grid container), display: subgrid makes the element a subgrid (which is a special type of grid container box) and consequently ignores its grid-template-* and grid-*-gap properties in favor of adopting the parent grid tracks that it spans.

3. Subgrids

A grid item can itself be a grid container by giving it display: grid. In this case the layout of its contents will be independent of the layout of the grid it participates in.

In some cases it might be necessary for the contents of multiple grid items to align to each other. A grid container that is itself a grid item can defer the definition of its rows and columns to its parent grid container by using display: subgrid, making it a subgrid.

In this case, the grid items of the subgrid participate in sizing the grid of the parent grid container, allowing the contents of both grids to align. Read more.

主要浏览器尚未实现此功能。谁知道什么时候。

在网格中,只有容器的流入子元素成为网格项并且可以接受网格属性。

对于网格项目 display: subgrid,项目的子项遵循容器的行。

根据 Grid Level 1 spec, display: subgrid has been deferred to Level 2.

目前,display: grid 网格项(即嵌套网格容器)在某些情况下可能会有用。

另一种可能的解决方法是 display: contents。方法解释在这里:

  • What is an alternative to css subgrid?

更多信息:

由于 subgrids are not supported at all, as of writing this answer, on browsers 除了最新的 Firefox v71,即使其他浏览器开始支持它,使用旧版本的用户至少会落后一段时间一年,直到足够多的用户升级他们的浏览器才能使用这样的新功能。

我设计了一种在祖先网格上对齐深层嵌套网格元素的方法:

从本质上讲,这个解决方案是将 display:contents 应用于网格的所有嵌套元素,直到那些希望用作网格项的元素,这有效地进行了反向继承,所以每个设置为 display:contents 的元素实际上是在投射其子元素的显示,因此最终将深层嵌套元素视为 .container 元素的直接子元素。

.container {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 10px;
  max-width: 500px;
  margin: auto;
}

.container div{
  display: contents;
}

input{ height: 40px; }
label{ align-self: center; }
<div class="container">
  <div>
    <div>
      <div>
        <label contenteditable>very long label</label>
        <input>
      </div>
    </div>
  </div>
  <div>
    <div>
      <div>
        <label contenteditable>short</label>
        <input>
      </div>
    </div>
  </div>
</div>

浏览器将其视为:

<div class="container">
  <label contenteditable>very long label</label>
  <input>
  <label contenteditable>short</label>
  <input>
</div>

在上面的示例中,标签是可编辑的,以展示网格轨道的动态特性,因此所有网格项目都是对齐的。

Codepen demo