好的,情况是这样的,假设我有一个包含未知数量项目的列表,可能是 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>
如果事先不知道您要显示的项目数量,我认为这是不可能的,对于您的情况,您可以这样做:
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>
但是行数必须事先定义。
理论上,您可以通过使用 “数量查询” 基于
:nth-*
选择器来使用 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 更好的解决方案。
我有一个未知数量的列表,它可能是 10 或 100
正如您已经观察到的那样,CSS 多列布局 使用纯 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;
}
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;
}
尝试以下操作:
ul {
list-style: none;
columns: 3;
-moz-column-count: 3;
-moz-column-gap: 1.5rem;
-moz-column-rule: none;
-webkit-column-count: 3;
-webkit-column-gap: 1.5rem;
-webkit-column-rule: none;
column-count: 3;
column-gap: 1.5rem;
column-rule: none;
}
<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>
我在这里使用了一些 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>