【问题标题】:Wrap CSS grid with auto placement使用自动放置包装 CSS 网格
【发布时间】:2019-07-23 18:29:53
【问题描述】:

我正在尝试构建一个包含类似卡片的项目的网格。每种类型的单元格(标题、图像、文本、按钮...)在每一行中的高度应相同,由最大单元格的内容决定,如下面的代码 sn-p 所示。

现在我试图限制列数,让卡片换行,就好像我在基于 flexbox 的解决方案中使用了flex-wrap: wrap;。列数应通过媒体查询确定。如果不使用尚不支持的subgrids,这可能吗?

此外,使用子网格的解决方案会是什么样子?我猜它会降级为当前浏览器中高度不等的单元格?

.grid {
  display: grid;
  grid-template-rows: repeat(4, auto);
  grid-gap: 10px;
  grid-auto-flow: column;
  grid-auto-columns: auto;
}
<div class="grid">

  <h2 class="a">Header 1</h2>
  <img class="b" src="https://placekitten.com/400/100" />
  <p class="c">text
  </p>
  <button class="d">Button</button>

  <h2 class="a">Header 2 is longer and may span multiple lines</h2>
  <img class="b" src="https://placekitten.com/400/100" />
  <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est.
  </p>
  <button class="d">Button</button>


  <h2 class="a">Header 1</h2>
  <img class="b" src="https://placekitten.com/400/100" />
  <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est, non ultricies lectus placerat eget.
  </p>
  <button class="d">Button</button>

  <h2 class="a">Header 1</h2>
  <img class="b" src="https://placekitten.com/400/100" />
  <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est, non ultricies lectus placerat eget. Suspendisse pulvinar arcu massa, quis
    varius velit facilisis tincidunt. Proin sed cursus orci.
  </p>
  <button class="d">Button</button>

  <h2 class="a">Header 1</h2>
  <img class="b" src="https://placekitten.com/400/100" />
  <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  </p>
  <button class="d">Button</button>
</div>

【问题讨论】:

  • 您需要将每张卡片包装在一个单独的 div 中......这将是正常的方法。没有 CSS 方法可以均衡不共享父元素的行或元素之间的高度。

标签: html css css-grid grid-layout


【解决方案1】:

这是我们需要 子网格 的一个很好的例子 - 对齐 网格表亲 在这个问题的布局中是必不可少的。

在浏览器实现Subgrids提议 2 级规范之前,我们只能包装 元素中的每一列,然后包装 它使用外部网格容器。

以下是 CSS Grid Layout Module Level 2Editor's Draft 的摘录:

2。子网格

一个网格项目本身可以是一个网格容器,方法是给它显示:grid;在这种情况下,其内容的布局将是 与其参与的网格布局无关。

在某些情况下可能需要多个网格的内容 相互对齐的项目。一个网格容器,它本身就是一个网格 item 可以将其行和列的定义推迟到其父项 网格容器,使其成为子网格。在这种情况下,网格项 子网格参与调整父网格的网格 容器,允许两个网格的内容对齐。

可以在here 找到讨论此问题的好读物。

这是一个使用嵌套网格容器的模型(子网格可能看起来像这样,但不会违反非等表亲规则) - 请参见下面的演示:

.wrapper {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
}

.grid {
  display: grid;
  grid-template-rows: repeat(4, 1fr);
  justify-items: flex-start;
  border: 1px solid #07c;
}

img {
  width: 100%;
}

button {
  align-self: center;
  justify-self: center;
}

p {
  padding: 0 10px;
}
<div class="wrapper">

  <div class="grid">
    <h2 class="a">Header 1</h2>
    <img class="b" src="https://placekitten.com/400/100" />
    <p class="c">text
    </p>
    <button class="d">Button</button>
  </div>

  <div class="grid">
    <h2 class="a">Header 2 is longer and may span multiple lines</h2>
    <img class="b" src="https://placekitten.com/400/100" />
    <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est.
    </p>
    <button class="d">Button</button>
  </div>

  <div class="grid">
    <h2 class="a">Header 1</h2>
    <img class="b" src="https://placekitten.com/400/100" />
    <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est, non ultricies lectus placerat eget.
    </p>
    <button class="d">Button</button>
  </div>

  <div class="grid">
    <h2 class="a">Header 1</h2>
    <img class="b" src="https://placekitten.com/400/100" />
    <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est, non ultricies lectus placerat eget. Suspendisse pulvinar arcu massa, quis
      varius velit facilisis tincidunt. Proin sed cursus orci.
    </p>
    <button class="d">Button</button>
  </div>

  <div class="grid">
    <h2 class="a">Header 1</h2>
    <img class="b" src="https://placekitten.com/400/100" />
    <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    </p>
    <button class="d">Button</button>
  </div>

</div>

一个可能的定义是:

.wrapper {
  display: grid; /* outer grid */
  /* sets a wrapping grid container with items of width around 400px */
  grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); 
}

.grid {
  grid-row: span 4; /* span 4 rows */
  display: grid;
  /* magic is here */
  grid-template-rows: subgrid; /* create a sub-grid with the 4 parent grid rows */
}

【讨论】:

  • 谢谢,您的模型适用于几乎等高元素的情况。可悲的是,我的用例更加多样化。关于子网格定义的问题:据我所知,子网格“占据”其父网格中的位置。网格行是由grid-row: span 4 在子网格中隐式创建的吗?
【解决方案2】:

你现在已经有了一个解决方案,它的浏览器支持并不理想,但无论如何都可以工作,那就是 display: content

您需要将元素包装在辅助 div 中,我将它们设置为类 card。然后,通过显示使该层的卡片消失:内容:

.grid {
  display: grid;
  grid-gap: 10px;
  grid-auto-columns: 1fr;
  grid-auto-flow: dense;
}

.card {
  display: contents;
}

.card:nth-child(odd) * {
  grid-column-start: 1;
}

.card:nth-child(even) * {
  grid-column-start: 2;
}

@media screen and ( min-width: 1300px) {
  .card:nth-child(3n + 0) * {
    grid-column-start: 3;
  }
  .card:nth-child(3n + 1) * {
    grid-column-start: 1;
  }
  .card:nth-child(3n + 2) * {
    grid-column-start: 2;
  }
}
<div class="grid">

  <div class="card">
    <h2 class="a">Header 1</h2>
    <img class="b" src="https://placekitten.com/400/100">
    <p class="c">text
    </p>
    <button class="d">Button</button>
  </div>

  <div class="card">
    <h2 class="a">Header 2 is longer and may span multiple lines</h2>
    <img class="b" src="https://placekitten.com/400/100">
    <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est.
    </p>
    <button class="d">Button</button>
  </div>

  <div class="card">
    <h2 class="a">Header 1</h2>
    <img class="b" src="https://placekitten.com/400/100">
    <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est, non ultricies lectus placerat eget.
    </p>
    <button class="d">Button</button>
  </div>

  <div class="card">
    <h2 class="a">Header 1</h2>
    <img class="b" src="https://placekitten.com/400/100">
    <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est, non ultricies lectus placerat eget. Suspendisse pulvinar arcu massa, quis
      varius velit facilisis tincidunt. Proin sed cursus orci.
    </p>
    <button class="d">Button</button>
  </div>

  <div class="card">
    <h2 class="a">Header 1</h2>
    <img class="b" src="https://placekitten.com/400/100">
    <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    </p>
    <button class="d">Button</button>
  </div>
</div>

我只是错过了最简单的解决方案:

由于您已经有一个平面 HTML,并且打算使用媒体查询,您可以使用相同的想法,(第 n 个选择器)但在平面 HTMl 上

.grid {
  display: grid;
  grid-gap: 10px;
  grid-auto-flow: dense;
  grid-auto-rows: 1fr;
}

.card {
  display: contents;
}

h2,
img,
p,
button {
  grid-column-start: 1;
}

h2:nth-of-type(even),
img:nth-of-type(even),
p:nth-of-type(even),
button:nth-of-type(even) {
  grid-column-start: 2;
}

@media screen and ( min-width: 1300px) {

h2:nth-of-type(3n + 1),
img:nth-of-type(3n + 1),
p:nth-of-type(3n + 1),
button:nth-of-type(3n + 1) {
  grid-column-start: 1;
}
h2:nth-of-type(3n + 2),
img:nth-of-type(3n + 2),
p:nth-of-type(3n + 2),
button:nth-of-type(3n + 2) {
  grid-column-start: 2;
}
h2:nth-of-type(3n),
img:nth-of-type(3n),
p:nth-of-type(3n),
button:nth-of-type(3n) {
  grid-column-start: 3;
}

}
<div class="grid">

  <h2 class="a">Header 1</h2>
  <img class="b" src="https://placekitten.com/400/100" />
  <p class="c">text
  </p>
  <button class="d">Button</button>

  <h2 class="a">Header 2 is longer and may span multiple lines</h2>
  <img class="b" src="https://placekitten.com/400/100" />
  <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est.
  </p>
  <button class="d">Button</button>


  <h2 class="a">Header 1</h2>
  <img class="b" src="https://placekitten.com/400/100" />
  <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est, non ultricies lectus placerat eget.
  </p>
  <button class="d">Button</button>

  <h2 class="a">Header 1</h2>
  <img class="b" src="https://placekitten.com/400/100" />
  <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis et cursus ligula. Maecenas non pharetra dui, eu tincidunt mi. Vivamus vitae luctus risus. Etiam vehicula sem est, non ultricies lectus placerat eget. Suspendisse pulvinar arcu massa, quis
    varius velit facilisis tincidunt. Proin sed cursus orci.
  </p>
  <button class="d">Button</button>

  <h2 class="a">Header 1</h2>
  <img class="b" src="https://placekitten.com/400/100" />
  <p class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  </p>
  <button class="d">Button</button>
</div>

【讨论】:

  • 有什么方法可以避免滚动并在空间不足时进行换行?
  • @TemaniAfif 只需将媒体查询设置在正确的断点。我已经编辑了答案(对于我已经拥有的媒体查询,为较小的屏幕添加另一个非常容易)。我还添加了另一个具有更好支持的答案
猜你喜欢
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-21
相关资源
最近更新 更多