Сделать столбцы контейнера сетки не строками
Я хочу, чтобы моя сетка была заполнена вертикально:
1 4 7
2 5 8
3 6 9
... arbitrary number of additional rows.
Вместо этого он заполняется горизонтально следующим образом:
1 2 3
4 5 6
7 8 9
Я хочу указать количество столбцов в моей сетке, а не количество строк.
Это то, что мой div выглядит со встроенным стилем CSS:
<div style="display:grid; grid-template-columns:1fr 1fr 1fr;">
<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>
Ответы
Ответ 1
Для вертикальной сетки, которая создает новые столбцы по мере необходимости, а строки не определены, рассмотрите возможность использования многостолбцовой компоновки CSS (пример). CSS Grid Layout (по крайней мере, текущая реализация - Уровень 1) не может выполнить эту задачу. Здесь проблема:
В CSS Grid Layout существует обратная рабочая взаимосвязь между свойствами grid-auto-flow
и grid-template-rows
/grid-template-columns
.
Точнее говоря, с помощью grid-auto-flow: row
(настройка по умолчанию) и grid-template-columns
оба определены, элементы сетки перемещаются красиво в горизонтальном направлении, автоматически создавая новые строки по мере необходимости. Эта концепция проиллюстрирована в коде в вопросе.
#container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-flow: row;
}
<div id="container">
<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
Другой вариант - сбросить CSS-сетку и использовать столбцы CSS, что делает именно то, что вы просите, а также иметь гораздо лучшую поддержку браузера.
.csscolumn {
-webkit-column-count: 3; /* Chrome, Safari, Opera */
-moz-column-count: 3; /* Firefox */
column-count: 3;
}
/* styling for this demo */
.csscolumn {
width: 50%;
}
.csscolumn + .csscolumn {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid;
}
<div class="csscolumn">
<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>
<div class="csscolumn">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
<div class="csscolumn">
<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>10</div>
</div>
Ответ 3
Больше, чем техническое упражнение, чем как практическое решение, вы можете получить какой-то результат с помощью определенных стилей в зависимости от количества элементов
Посмотрите, как это работает:
.item:first-child:nth-last-child(n+4):nth-last-child(-n + 6) ~ .item:nth-child(n+3)
первый селектор
.item:first-child:nth-last-child(n+4):nth-last-child(-n + 6)
активен, наш список имеет от 4 до 6 элементов. В этом случае какой-то элемент будет как в первом, так и во втором.
В этом случае мы хотим, чтобы в первом столбце находилось 2 элемента. задайте оставшиеся предметы (начиная с третьего) с помощью
~ .item:nth-child(n+3)
и поместите их во второй столбец. Аналогичное правило, теперь для 5-го и далее
~ .item:nth-child(n+5)
помещает другие элементы в третий столбец. Эти 2 правила имеют одинаковый приоритет и нацелены на оба последних элемента, поэтому критически важно, чтобы они отображались в этом порядке.
Нам нужно повторить аналогичные правила до максимального количества элементов, которые могут присутствовать (возможно, задания для препроцессора)
var elements = 5;
function add () {
var ctn = document.getElementById("container");
var ele = document.createElement("div");
elements ++;
ele.innerHTML = elements;
ele.className = "item";
ctn.appendChild (ele);
}
#container {
width: 90%;
border: solid 1px red;
display: grid;
grid-template-rows: 33% 33% 33%;
grid-auto-flow: column dense;
}
.item {
width: 90%;
height: 80px;
background-color: lightgreen;
margin: 10px;
grid-column: 1;
}
.item:first-child:nth-last-child(n+4):nth-last-child(-n + 6) ~ .item:nth-child(n+3) {
background-color: yellow;
grid-column: 2;
}
.item:first-child:nth-last-child(n+4):nth-last-child(-n + 6) ~ .item:nth-child(n+5) {
background-color: tomato;
grid-column: 3;
}
.item:first-child:nth-last-child(n+7):nth-last-child(-n + 9) ~ .item:nth-child(n+4) {
background-color: burlywood;
grid-column: 2;
}
.item:first-child:nth-last-child(n+7):nth-last-child(-n + 9) ~ .item:nth-child(n+7) {
background-color: blueviolet;
grid-column: 3;
}
.item:first-child:nth-last-child(n+10):nth-last-child(-n + 12) ~ .item:nth-child(n+5) {
background-color: darkcyan;
grid-column: 2;
}
.item:first-child:nth-last-child(n+10):nth-last-child(-n + 12) ~ .item:nth-child(n+9) {
background-color: chartreuse;
grid-column: 3;
}
.item:first-child:nth-last-child(n+13):nth-last-child(-n + 15) ~ .item:nth-child(n+6) {
background-color: yellow;
grid-column: 2;
}
.item:first-child:nth-last-child(n+13):nth-last-child(-n + 15) ~ .item:nth-child(n+11) {
background-color: tomato;
grid-column: 3;
}
<button onclick="add()">Add</button>
<div id="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
Ответ 4
Простейший метод, который я видел, выглядит следующим образом:
.grid {
display: grid;
grid-auto-flow: column;
grid-gap: 1px;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(5, auto);
}
<div class="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>10</div>
<div>11</div>
<div>12</div>
<div>13</div>
</div>
Ответ 5
Вот один подход, основанный на CSS Grid, с использованием javascript и CSSOM для вставки пары:
transform: translate(x, y)
правил в созданную таблицу стилей.
Два правила преобразования (всего два, на основе сетки, состоящей из 3 столбцов, смещают нижние элементы исходной сетки одного столбца, перемещая элементы вверх и вправо.
Следовательно, вы можете добавить любое количество элементов в сетку с одним столбцом, и скрипт всегда будет настраивать сетку так, чтобы она имела три столбца более или менее равного размера.
Если столбцы не могут быть одинакового размера, то более высокий столбец всегда будет первым и/или вторым столбцом (никогда не справа, третьим столбцом).
Рабочий пример (9 блоков сетки):
var numberOfColumns = 3;
document.head.appendChild(document.createElement('style'));
var newStyles = document.styleSheets[(document.styleSheets.length - 1)];
var myGrid = document.getElementsByClassName('my-grid')[0];
var myGridUnits = myGrid.getElementsByTagName('div');
var tallColumn = Math.ceil(myGridUnits.length / numberOfColumns);
var shortColumn = Math.floor(myGridUnits.length / numberOfColumns);
var nextUnit = 1;
var unitsRemaining = myGridUnits.length;
var xTranslate, yTranslate;
var columns = [];
for (var i = 0; i < (numberOfColumns - 1); i++) {
if (unitsRemaining % shortColumn === 0) {
columns.push(shortColumn);
}
else {
columns.push(tallColumn);
}
nextUnit += columns[(columns.length - 1)];
unitsRemaining -= columns[(columns.length - 1)];
xTranslate = ((i + 1) * 48);
yTranslate = 0;
columns.forEach(function(columnHeight){yTranslate += (columnHeight * 48);});
newStyles.insertRule('.my-grid div:nth-of-type(n+' + nextUnit + ') {transform: translate(' + xTranslate + 'px, ' + (0 - (yTranslate)) + 'px);}', newStyles.cssRules.length);
}
.my-grid {
display: inline-grid;
grid-row-gap: 6px;
}
.my-grid div {
width: 40px;
height: 40px;
line-height: 40px;
text-align: center;
border: 1px solid rgb(127, 127, 127);
}
<div class="my-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>