Je veux que ma grille remplisse verticalement comme ceci:
1 4 7
2 5 8
3 6 9
... arbitrary number of additional rows.
Au lieu de cela, il se remplit horizontalement comme ceci:
1 2 3
4 5 6
7 8 9
Je veux spécifier le nombre de colonnes dans ma grille, pas le nombre de lignes.
Voici à quoi ressemble ma div avec le style CSS intégré:
<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>
Il est important que ma grille ait 3 colonnes de largeur, mais je veux que les éléments soient renseignés par colonne et non par ligne. Est-ce possible dans CSS Grid? J'ai lu ceci https://css-tricks.com/snippets/css/complete-guide-grid/ mais je n'ai rien vu à propos de la commande.
CSS Flexbox a flex-direction
, n’existe-t-il pas un attribut semblable à celui de CSS Grid?
Pour une grille à flux vertical qui crée de nouvelles colonnes si nécessaire et dont les lignes ne sont pas définies, envisagez d'utiliser CSS Présentation multicolonnes ( exemple ). CSS Grid Layout (au moins l’implémentation actuelle - Level 1 ) ne peut pas exécuter cette tâche. Voici le problème:
Dans CSS Grid Layout, il existe une relation inverse entre les propriétés grid-auto-flow
et grid-template-rows
grid-template-columns
.
Plus précisément, avec grid-auto-flow: row
(paramètre par défaut) et grid-template-columns
tous les deux définis, les éléments de la grille se déroulent bien dans une direction horizontale, créant automatiquement de nouvelles lignes si nécessaire. Ce concept est illustré dans le code de la question.
#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>
Cependant, avec le passage à grid-template-rows
, les éléments de la grille sont empilés dans une seule colonne.
#container {
display: grid;
grid-template-rows: 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>
Il n'y a pas de création automatique de colonnes avec grid-auto-flow: row
et grid-template-rows
. grid-template-columns
doit être défini (d'où la relation inverse avec grid-auto-flow
).
#container {
display: grid;
grid-template-rows: 1fr 1fr 1fr;
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>
Le même comportement est vrai dans le scénario inverse.
Avec grid-auto-flow: column
et grid-template-rows
tous deux définis, les éléments de la grille se déplacent bien dans une direction verticale, créant automatiquement de nouvelles colonnes si nécessaire.
#container {
display: grid;
grid-template-rows: 1fr 1fr 1fr;
grid-auto-flow: column;
}
<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>
Cependant, avec le passage à grid-template-columns
, les éléments de la grille sont empilés sur une seule ligne. (C'est le problème que la plupart des gens demandent, y compris dans cette question.)
#container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-flow: column;
}
<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>
Il n'y a pas de création automatique de lignes. Cela nécessite que grid-template-rows
soit défini. (C’est la solution la plus souvent fournie, mais elle est généralement rejetée car les modèles comportent un nombre de lignes variable.)
#container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-auto-flow: column;
}
<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>
Par conséquent, considérons une solution de mise en page _/multi-colonnes , comme suggéré ci-dessus.
Référence de spécification: 7.7. Positionnement automatique: la propriété grid-auto-flow
Une autre option consiste à supprimer la grille CSS et à utiliser les colonnes CSS, ce qui correspond exactement à ce que vous demandez et offre une meilleure prise en charge du navigateur.
.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>
Plus comme un exercice technique que comme une solution pratique, vous pouvez obtenir votre résultat en utilisant des styles spécifiques en fonction du nombre d'articles.
Voyons voir comment ça fonctionne:
.item:first-child:nth-last-child(n+4):nth-last-child(-n + 6) ~ .item:nth-child(n+3)
le premier sélecteur
.item:first-child:nth-last-child(n+4):nth-last-child(-n + 6)
est actif est notre liste contient entre 4 et 6 éléments. Dans ce cas, certains éléments seront à la fois dans la première condition et dans la seconde.
Dans ce cas, nous voulons que 2 éléments soient dans la première colonne. cibler les éléments restants (à partir du troisième) avec
~ .item:nth-child(n+3)
et les mettre sur la deuxième colonne. Une règle similaire, maintenant à partir du 5
~ .item:nth-child(n+5)
met les autres éléments dans la troisième colonne. Ces deux règles ont la même priorité et ciblent les deux derniers éléments. Il est donc essentiel qu’elles apparaissent dans cet ordre.
Nous devons répéter des règles similaires dans la limite du nombre d'éléments pouvant être présents (probablement un travail pour un pré-processeur)
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>
La méthode la plus simple que j'ai vue suit:
.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>
Voici une approche basée sur CSS Grid utilisant JavaScript et le CSSOM pour insérer une paire de:
transform: translate(x, y)
règles dans une feuille de style générée.
Les deux règles de transformation (il n'y a que seulement deux, selon que la grille est 3 colonnes de large déplacent les éléments inférieurs de la grille à une colonne d'origine, en déplaçant les éléments vers le haut et le droit.
Par conséquent, vous pouvez ajouter un nombre quelconque d’éléments à la grille à une colonne et le script ajustera toujours la grille afin qu’elle ait trois colonnes de taille plus ou moins égale.
Si les colonnes ne peuvent pas être de tailles exactement égales, la ou les colonnes les plus hautes seront toujours la première et/ou la deuxième colonne (jamais la troisième, la plus à droite).
Exemple de travail (9 unités de grille):
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>
Exemple de travail (10 unités de grille):
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>10</div>
</div>
Exemple de travail (11 unités de grille):
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>10</div>
<div>11</div>
</div>
Exemple de travail (14 unités de grille):
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>10</div>
<div>11</div>
<div>12</div>
<div>13</div>
<div>14</div>
</div>