3 столбца (сверху вниз) с использованием сетки CSS
Хорошо, здесь ситуация, скажем, у меня есть список с неизвестным количеством элементов, это может быть 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>
Ответы
Ответ 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>
Ответ 2
Теоретически вы можете добиться этого с помощью CSS Grid, используя "Количество запросов" на основе :nth-*
селекторов, например:
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>
Ответ 3
У меня есть список с неизвестным количеством элементов, это может быть 10 или 100
Как вы уже заметили, CSS Multi-Column Layout создает желаемый макет с чистым CSS - без предварительного уведомления количества элементов в контейнере.
Это не относится к сеткам CSS - вам нужно заранее знать количество элементов в сетке, чтобы вычислить необходимое количество строк, что является довольно ограниченным.
Поэтому я бы посоветовал вам придерживаться многоколоночного макета для вашего макета.
Предполагая, что вышеуказанное ограничение одобрено, вы можете создать макет с помощью css следующим образом:
(Примечание: @And уже ответили на это, но для чего это стоит здесь небольшое объяснение)
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;
}
Ответ 4
Я использовал здесь немного JavaScript. Где "lst" является идентификатором UL. Я использовал переменные 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>