如何扁平化嵌套的div的CSS网格显示它们?

问题描述 投票:2回答:3

我生成从其中被认为是两列宽的对象的表(用vue.js)。每列来自对象的键和值。这相当于下列实际HTML:

<div id="table">
  <div>
    <div>
      this is something long on the first row
    </div>
    <div>
      short 1st row
    </div>
  </div>
  <div>
    <div>
      wazaa 2nd row
    </div>
    <div>
      wazii 2nd row
    </div>
  </div>
</div>

我用CSS网格这些div格式化为一个2x2的网格,这是我预期为

this is something long on the first row | short 1st row
wazaa 2nd row                           | wazii 2nd row

代码做到这一点:

#table {
  display: grid;
  grid-template-columns: auto 1fr;
}
<div id="table">
  <div>
    <div>
      this is something long on the first row
    </div>
    <div>
      short 1st row
    </div>
  </div>
  <div>
    <div>
      wazaa 2nd row
    </div>
    <div>
      wazii 2nd row
    </div>
  </div>
</div>

其结果是不是我期望:两个最深div行为应该像他们外面的grid显示:它们堆叠在彼此的顶部。

我希望他们继承格行为:基于列的模板,因为他们去对齐。如何实现这一目标?

html css css-grid
3个回答
2
投票

因为这些div超出范围以外的网格属性不应用到你的内容的div。

网格格式仅限于父子关系。这意味着,一个网格容器始终是家长和网格项目永远是孩子。超出了孩子的网格容器的后代都没有网格布局的一部分,不会接受网格属性。

因为你的内容的div两个层次下来从电网容器(#table),使它们的孙子不是孩子,他们不是电网项目,将不接受格属性。

更多细节:Grid properties not working on elements inside grid container


但也有例外的规则之上,但他们没有太多的或任何浏览器的支持。

display: contents是覆盖在another answer to this post。它使一个元件被忽略为由父一个包含块,因此父将识别出它的孙子作为正常儿童。但现在这种方法是用于生产目的有效无用的,因为它有weak browser support

在这种情况下,更适当的解决方案将是display: subgrid,这使得超出儿童网格容器的后代(即,网格项目的孩子)尊重所述容器的线。但是这项功能有没有浏览器的支持。

更多细节:Positioning content of grid items in primary container (subgrid feature)


如果你想要一个纯CSS的解决方案,或许电网和柔性的组合可以提供帮助。

这里是一个笼统的概念。没有更改HTML。

#table {
  display: grid;
  grid-template-columns: 1fr;
}

#table > div {
  display: flex;
}

#table > div > div {
  flex: 1;
}
<div id="table">
  <div>
    <div>
      this is something long on the first row
    </div>
    <div>
      short 1st row
    </div>
  </div>
  <div>
    <div>
      wazaa 2nd row
    </div>
    <div>
      wazii 2nd row
    </div>
  </div>
</div>

3
投票

您可以使用display:contentshttps://caniuse.com/#feat=css-display-contents)来解决这个问题:

#table {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-gap:10px;
}

#table > div {
  display:contents;
}
<div id="table">
  <div>
    <div>
      this is something long on the first row
    </div>
    <div>
      short 1st row
    </div>
  </div>
  <div>
    <div>
      wazaa 2nd row
    </div>
    <div>
      wazii 2nd row
    </div>
  </div>
</div>

或者使用显示表象下面这样:

#table {
  display: table;
}

#table > div {
  display:table-row;
}
#table > div > div {
  display:table-cell;
  padding:5px;
}
#table > div > div:first-child {
  white-space:nowrap;
  width:10%;
}
<div id="table">
  <div>
    <div>
      this is something long on the first row
    </div>
    <div>
      short 1st row
    </div>
  </div>
  <div>
    <div>
      wazaa 2nd row
    </div>
    <div>
      wazii 2nd row
    </div>
  </div>
</div>

1
投票

如果可能的话,我会建议改变你的Vue.js代码不会产生不必要的div嵌套水平,并使其如下:

#table {
  display: grid;
  grid-template-columns: auto 1fr;
}
#table > div { border: 1px dotted black; }
<div id="table">
  <div>
    this is something long on the first row
  </div>
  <div>
    short 1st row
  </div>
  <div>
    wazaa 2nd row
  </div>
  <div>
    wazii 2nd row
  </div>
</div>

如果这是不可能的,那么你可以使用JavaScript来实现相同的,但客户端。你也可以使用display:contents从@Temani的答案,但它与可能马车结果相当有限的浏览器的支持。


如果你喜欢一个JavaScript解决方案,而不是,您可以使用此:

(function() {
  var table = document.getElementById("table");
  var divs = [...table.childNodes]; // use ... to enumerate the items immediately
  for (var i = 0; i < divs.length; i++) {
    var div = divs[i];
    while (div.childNodes.length > 0)
      table.appendChild(div.childNodes[0]);
    div.remove();
  }
})()
#table {
  display: grid;
  grid-template-columns: auto 1fr;
}
#table > div { border: 1px dotted black }
<div id="table">
  <div>
    <div>
      this is something long on the first row
    </div>
    <div>
      short 1st row
    </div>
  </div>
  <div>
    <div>
      wazaa 2nd row
    </div>
    <div>
      wazii 2nd row
    </div>
  </div>
</div>
© www.soinside.com 2019 - 2024. All rights reserved.