【问题标题】:3 columns grid (top to bottom) using grid CSS使用网格 CSS 的 3 列网格(从上到下)
【发布时间】:2018-11-14 13:39:12
【问题描述】:

好的,情况就是这样,假设我有一个包含未知数量的项目的列表,可能是 10 或 100,我想将它们排列在 3 列中,从上到下而不是从左到右。

现在我可以使用columns: 3;column-gap: 10px; 来实现这一点,一切都很好。

我的问题是,如何在不知道项目数量的情况下使用display: grid; 达到相同的结果?

我知道如果您有固定数量的项目,您可以使用 CSS Grid 来实现这一点,但是动态项目是否可以实现?当然不用 JS。

ul {
  list-style: none;
  columns: 3;
  column-gap: 10px;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
  <li>11</li>
  <li>12</li>
  <li>13</li>
  <li>14</li>
  <li>15</li>
  <li>16</li>
  <li>17</li>
  <li>18</li>
  <li>19</li>
  <li>20</li>
  <li>21</li>
  <li>22</li>
</ul>

【问题讨论】:

标签: html css css-grid


【解决方案1】:

如果事先不知道您要显示的项目数量,我认为这是不可能的,对于您的情况,您可以这样做:

ul {
   display: grid;
   grid-auto-flow: column;
   grid-template-rows: repeat(8, 1fr);
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
  <li>11</li>
  <li>12</li>
  <li>13</li>
  <li>14</li>
  <li>15</li>
  <li>16</li>
  <li>17</li>
  <li>18</li>
  <li>19</li>
  <li>20</li>
  <li>21</li>
  <li>22</li>
</ul>

但行数必须事先定义。

【讨论】:

  • 我知道固定数量的项目很容易,但我问的是未知数量的项目,这是棘手的部分。
  • 是的,就像我说的,我不认为只有 css 网格才有可能
【解决方案2】:

理论上,您可以通过基于:nth-* 选择器的"Quantity queries" 使用CSS Grid 来实现这一点,如下所示:

ul {
  list-style: none;
  display: grid;
  grid-auto-flow: row dense;
  grid-template-columns: repeat(3, 1fr);
  grid-column-gap: 10px;
}

/* by default, items go in first column */
li { grid-column: 1; }

/* if there are 1 to 3 items, the 2nd one goes to 2nd column and the 3rd one goes to 3rd column */
li:first-child:nth-last-child(n + 1):nth-last-child(-n + 3) ~ li:nth-child(n + 2):nth-child(-n + 2) { grid-column: 2; }
li:first-child:nth-last-child(n + 1):nth-last-child(-n + 3) ~ li:nth-child(n + 3) { grid-column: 3; }

/* ... */

/* if there are 19 to 21 items, items 8-14 to 2nd column and items 15+ to 3rd one */
li:first-child:nth-last-child(n + 19):nth-last-child(-n + 21) ~ li:nth-child(n + 8):nth-child(-n + 14) { grid-column: 2; }
li:first-child:nth-last-child(n + 19):nth-last-child(-n + 21) ~ li:nth-child(n + 15) { grid-column: 3; }

/* if there are 22 to 24 items, items 9-16 to 2nd column and items 17+ to 3rd one */
li:first-child:nth-last-child(n + 22):nth-last-child(-n + 24) ~ li:nth-child(n + 9):nth-child(-n + 16) { grid-column: 2; }
li:first-child:nth-last-child(n + 22):nth-last-child(-n + 24) ~ li:nth-child(n + 17) { grid-column: 3; }

/* if there are 25 to 27 items, items 10-18 to 2nd column and items 19+ to 3rd one */
li:first-child:nth-last-child(n + 25):nth-last-child(-n + 27) ~ li:nth-child(n + 10):nth-child(-n + 18) { grid-column: 2; }
li:first-child:nth-last-child(n + 25):nth-last-child(-n + 27) ~ li:nth-child(n + 19) { grid-column: 3; }

/* and so on */
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
  <li>11</li>
  <li>12</li>
  <li>13</li>
  <li>14</li>
  <li>15</li>
  <li>16</li>
  <li>17</li>
  <li>18</li>
  <li>19</li>
  <li>20</li>
  <li>21</li>
  <li>22</li>
</ul>

但是,这种方法并不实用。在我看来,这里 CSS 多列布局是比 CSS Grid 更好的解决方案。

【讨论】:

  • 我同意这很麻烦而且不实用,我想我会坚持使用多列布局。
【解决方案3】:

我有一个包含未知数量项目的列表,可能是 10 或 100

正如您已经观察到的,CSS Multi-Column Layout 使用纯 CSS 生成所需的布局 - 无需事先知道容器中的项目数。

这不是 CSS 网格的情况 - 您必须提前知道网格中的项目数才能计算必要的行数 - 这是一个很大的限制。

所以我建议您坚持使用多列布局


假设上述限制是可以的 - 那么您可以使用 css 创建布局,如下所示:

(注意:@Ander 已经回答了这个问题,但这里有一个小的解释)

1) 在网格容器上将grid-auto-flow 属性更改为column - 这会垂直而不是水平地布置网格项(默认设置)。

2) 知道项目数后,您可以计算创建平衡网格所需的行数,如下所示:

#rows =  ceil( #items / #columns )

所以对于 22 项 - # rows = ceil(22/3) = 8

ul {
   display: grid;
   grid-auto-flow: column; /* 1 */
   grid-template-rows: repeat(8, 1fr);  /* 2 */
}

我们可以使用 SASS 稍微改进这个解决方案 - 生成一个更通用的解决方案来计算行数。 (SASS有一个ceil函数)

ul {
  list-style: none;
  padding: 0;
  display:grid;
  $num-items: 22;
  $num-cols: 3;
  $num-rows: ceil($num-items / $num-cols);
  grid-template-columns: repeat($num-cols, 1fr);
  grid-template-rows: repeat($num-rows, 1fr);
  grid-auto-flow: column;
  border: 5px solid gold;
}

Codepen Demo


FWIW:这是一个替代解决方案,它使用 nth-child 选择器而无需更改 grid-auto-flow 属性。不幸的是,它具有相同的限制,即必须提前知道#items。

li:nth-child(-n + 24) {
  grid-column: 3;
}

li:nth-child(-n + 16) {
  grid-column: 2;
}

li:nth-child(-n + 8) {
  grid-column: 1;
}

SASS Codepen

【讨论】:

    【解决方案4】:

    我在这里使用了一点 JavaScript。其中 'lst' 是 UL 的 id。我使用 CSS 变量来传递 UL 中元素的值,并最终根据要求计算所需的列。唯一的缺点是我们需要检查总元素数是奇数还是偶数。

    <script>
     var list = document.getElementById("lst").childElementCount;
    document.getElementById("lst").style.setProperty('--x',list/2);
    </script>
    
    <style>
        ul {
              list-style:none;
              display: grid;
              grid-auto-flow:column;
              grid-template-rows:repeat(var(--x),1fr);
             }
    </style>
    

    【讨论】:

    • 这没有回答问题,每列的项目必须从上到下排序。
    • @UtkarshBais,我的想法是不使用 JS,我在问是否可以使用 CSS Grid 实现相同的布局。
    • @Ruby 我想,只是尝试用最少的 JavaScript 来实现结果。可能会帮助解决简单问题的人。
    猜你喜欢
    • 2014-11-20
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多