Ok, here's the situation, let's say I have a list with unknown number of items, it could be 10 or a 100, and I want to lay them out in 3 columns going top to bottom not left to right.
Right now I can achieve this using columns: 3;
and column-gap: 10px;
That's all fine and everything.
My question is, how to achieve the same results using display: grid;
without knowing the number of items?
I know you can achieve this with CSS Grid if you have a fixed number of items, but is it possible with dynamic items? without using JS of course.
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>
By using grid-template-columns: repeat(3, 1fr) on grid container you will get layout with 3 columns of equal width, and grid layout will by default make all items in each row equal height.
I don't think this is possible without previously know the number of items that you want to display, for your case you could do this:
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>
But the number of rows have to be defined previously.
In theory, you can kind of achieve this with CSS Grid by using "Quantity queries" based on :nth-*
selectors, like this:
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>
However, this approach isn't practical. In my opinion, the CSS Multi-column layout is the better solution here than CSS Grid.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With