【问题标题】:Create a CSS Grid that flows by column, with dynamic columns and rows based on content创建一个按列流动的 CSS 网格,具有基于内容的动态列和行
【发布时间】:2018-04-10 23:09:11
【问题描述】:

我有一个动态数量的元素(所有尺寸都相同)。我想将它们放置在网格中,以便它们按列排序,具有基于可用容器宽度的动态列数,以及基于元素数的动态行数。

例如,假设有 9 个元素:

1 4 7
2 5 8
3 6 9

但如果容器宽度扩大:

1 3 5 7 9
2 4 6 8

或缩小:

1 6
2 7
3 8
4 9
5

当项目按行而不是按列定位时,这可以正常工作。此外,如果我明确设置行数,它可以正常工作,但如果我对行和列都使用自动填充,它只会在一行中显示所有内容。

这是一个简单的示例,我希望它被渲染为 3x3 网格: https://codepen.io/anon/pen/ZxPQNd

#grid {
  width: 320px;
  border: 1px solid red;
  display: grid;
  grid-gap: 10px;
  grid-auto-flow: column;
  grid-template-rows: repeat(auto-fill, 100px);
  grid-template-columns: repeat(auto-fill, 100px);
  grid-auto-columns: 100px;
  grid-auto-rows: 100px;
}

#grid>div {
  background: lime;
}
<div id="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>

【问题讨论】:

  • 你试过弹性查询和媒体查询吗?
  • 为什么会呈现为 3x3 网格?它为列占用尽可能多的空间,在这种情况下就足够了。
  • 我认为这个问题最适合 column-count 而不是 display: grid
  • 尽量避免媒体查询,因为它们需要离散的大小,并且列数仍然需要明确的列数,而我希望它自动计算出适合可用的列数空间。

标签: html css css-grid


【解决方案1】:

您想要的布局可以通过使用 column-width 属性的 CSS 多列布局来实现。演示:

#grid {
  border: 1px solid red;
  column-width: 100px;
  column-gap: 10px;
}

#grid > div {
  break-inside: avoid-column; /* Prevent element from breaking */
  page-break-inside: avoid; /* Prevent element from breaking in Firefox */
  background: lime;
  width: 100px;
  height: 100px;
  margin-bottom: 10px;
}
<div id="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>

【讨论】:

    【解决方案2】:

    当项目按行而不是按列定位时,这可以正常工作。

    这是因为块元素默认占用其父元素的整个宽度。

    但是这种行为不会扩展到高度。默认情况下,大多数元素都是其内容的高度(即没有额外的空间)。

    基本上,您的容器设置为width: 100%height: auto。对于垂直轴中的行行为添加height: 100vh

    更多信息:How to make a div 100% height of the browser window?

    #grid {
      width: 320px;
      border: 1px solid red;
      display: grid;
      grid-gap: 10px;
      grid-auto-flow: column;
      grid-template-rows: repeat(auto-fill, 100px);
      grid-template-columns: repeat(auto-fill, 100px);
      grid-auto-columns: 100px;
      grid-auto-rows:  100px;
      height: 100vh; /* NEW */
    }
    
    #grid > div {
      background: lime;
    }
    <div id="grid">
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <div>4</div>
      <div>5</div>
      <div>6</div>
      <div>7</div>
      <div>8</div>
      <div>9</div>
    </div>

    在基于屏幕大小的网格项目重新排序方面,grid-auto-flow: row 项目将响应容器宽度。使用grid-auto-flow: column,项目将响应容器高度。要使列流动的项目响应宽度调整需要一些技巧。

    更多信息:Make grid items fill columns not rows

    【讨论】:

    • 但我不希望网格占据容器的整个高度,更不用说视口了。我只希望它与内容要求的一样高。
    • 网格容器应该如何知道内容需要什么?
    • 通过计算?目前这可能是不可能的,但这是一个相对简单的计算。如果容器是 400px 宽,有 9 个子元素,每个 100x100px,间隔 10px,那么很容易计算出必须有 3 列(320px)和 3 行。显然,这只有在子维度已知时才有效(网格自动行/列?)。在我的脑海中,我所描述的内容非常简单,但目前看来,这对于 CSS 网格来说是不可能的。
    【解决方案3】:

    OP 的问题完全正确。您要显示的元素数量不确定,并且要在其中显示它们的视口宽度不确定。并且您想在网格中显示元素。

    根据视口的宽度,您需要更多或更少的列。所以问题是如何设置它。

    想到的一个解决方案是使用 CSS 媒体查询来测试视口宽度,然后相应地更改您的布局。但这很乏味并且容易出错。您真正想要的是一个独立于视口宽度工作的解决方案。

    最简单的解决方案是,如果你所有的元素都是统一固定的宽度,那就是使用 flexbox。你可以试试这样的:

    #grid {
      display: flex;
      flex-wrap: wrap;
    }
    
    #grid div {
      flex: 1 0 110px;
      background-color: yellow;
      width: 100px;
      height: 100px;
      margin: 10px;
      max-width: 100px;
      text-align: center;
    }
    <div id="grid">
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <div>4</div>
      <div>5</div>
      <div>6</div>
      <div>7</div>
      <div>8</div>
      <div>9</div>
    </div>

    但您可能还希望元素扩展以填充水平空间,同时仍保持统一的网格。为此,您可以使用 CSS 网格。诀窍是在 grid-template-columns 属性上使用重复和最小值:

    #grid {
      display: grid;
        grid-auto-flow: row;
        grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
        grid-template-rows: repeat(auto-fill, 1fr);
        column-gap: 10px;
        row-gap: 10px;
    }
    
    #grid div {
      background-color: yellow;
      height: 100px;
      text-align: center;
    }
    <div id="grid">
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <div>4</div>
      <div>5</div>
      <div>6</div>
      <div>7</div>
      <div>8</div>
      <div>9</div>
    </div>

    【讨论】:

    • 这里介绍的解决方案没有考虑“从上到下,然后从左到右”的排序要求(困难的部分),而是按照“从左到右,然后从上到下”排序(这是微不足道的)。
    猜你喜欢
    • 1970-01-01
    • 2019-09-06
    • 2017-09-16
    • 2023-04-03
    • 2019-07-18
    • 2020-11-15
    • 2021-03-14
    • 1970-01-01
    • 2021-03-16
    相关资源
    最近更新 更多