web-dev-qa-db-fra.com

Ordre inverse des colonnes dans la disposition de grille CSS

J'espérais utiliser CSS Grid pour inverser l'ordre apparent de deux divisions côte à côte, où l'une des divisions croît arbitrairement (je ne veux pas utiliser de flottants).

J'ai créé un plunkr ici: http://plnkr.co/edit/6WZBnHbwhD7Sjx2ovCO7?p=preview

#container {
  grid-template-columns: 240px 1fr;
  display: grid;
}

.a {
  background: yellow;
}

.b {
  background: blue;
  color: white;
}

#container>.a {
  grid-column: 1;
}

#container>.b {
  grid-column: 2;
}

#container.reverse>.a {
  grid-column: 2;
}

#container.reverse>.b {
  grid-column: 1;
}
<div id="container" class="reverse" style="width: 800px;">
  <div class="a">A</div>
  <div class="b">B</div>
</div>

L'essentiel est que lorsque j'ai le .reverse classe appliquée (pour que vous voyiez B | A), B est décalé sur une nouvelle ligne, il ressemble donc plus à:

          | A
B

Si j'inverse l'ordre des documents de .a avec .b, cela revient à la normale (mais bien sûr, si je laisse tomber le .reverse classe, j'ai le même problème).

Pourquoi est-ce et comment puis-je y remédier?

14
Rob

Comme l'algorithme de placement automatique de la grille présente les éléments dans le conteneur, il utilise prochain disponible cellules vides ( source ).

Dans votre code source, l'élément A précède l'élément B:

<div id="container" class="reverse" style="width: 800px;">
   <div class="a">A</div>
   <div class="b">B</div>
</div>

Par conséquent, le conteneur de grille place d'abord A, puis utilise l'espace disponible suivant pour placer B.

Par défaut, l'algorithme de placement automatique regarde linéairement à travers la grille sans retour en arrière; s'il doit sauter des espaces vides pour placer un élément plus grand, il ne reviendra pas pour remplir ces espaces. Pour modifier ce comportement, spécifiez le mot clé dense dans grid-auto-flow.

http://www.w3.org/TR/css3-grid-layout/#common-uses-auto-placement


grid-auto-flow: dense

Une solution à ce problème ( comme vous l'avez noté ) consiste à remplacer la valeur par défaut grid-auto-flow: row avec grid-auto-flow: dense.

Avec grid-auto-flow: dense, l'algorithme de placement automatique de la grille cherchera à remplir les cellules inoccupées avec des éléments qui correspondent.

#container {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-auto-flow: dense; /* NEW */
}

7.7. Placement automatique: le grid-auto-flow propriété

Les éléments de grille qui ne sont pas explicitement placés sont automatiquement placés dans un espace inoccupé du conteneur de grille par l'algorithme de placement automatique.

grid-auto-flow contrôle le fonctionnement de l'algorithme de placement automatique, en spécifiant exactement comment les éléments placés automatiquement sont transférés dans la grille.

dense

S'il est spécifié, l'algorithme de placement automatique utilise un algorithme d'emballage "dense", qui tente de combler les trous plus tôt dans la grille si des éléments plus petits apparaissent plus tard. Cela peut faire apparaître des articles hors service, ce qui remplirait les trous laissés par des articles plus gros.

#container {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-auto-flow: dense; /* NEW */
}

.a {
  background: yellow;
}

.b {
  background: blue;
  color: white;
}

#container>.a {
  grid-column: 1;
}

#container>.b {
  grid-column: 2;
}

#container.reverse>.a {
  grid-column: 2;
}

#container.reverse>.b {
  grid-row: 1;
  grid-column: 1;
}
<div id="container" class="reverse" style="width: 800px;">
  <div class="a">A</div>
  <div class="b">B</div>
</div>

grid-row: 1

Une autre solution serait de simplement définir la ligne du deuxième élément.

#container>.b {
  grid-column: 2;
  grid-row: 1; /* NEW */
}
#container {
  display: grid;
  grid-template-columns: 240px 1fr;
}

.a {
  background: yellow;
}

.b {
  background: blue;
  color: white;
}

#container>.a {
  grid-column: 1;
}

#container>.b {
  grid-column: 2;
  grid-row: 1; /* NEW */
}

#container.reverse>.a {
  grid-column: 2;
}

#container.reverse>.b {
  grid-row: 1;
  grid-column: 1;
}
<div id="container" class="reverse" style="width: 800px;">
  <div class="a">A</div>
  <div class="b">B</div>
</div>
17
Michael_B

Bien que les solutions ci-dessus fonctionnent pour cet exemple spécifique, ce n'est pas la bonne façon de résoudre votre question. Il existe une propriété CSS à laquelle Grid Layout adhère appelée direction. direction: rtl vous donnera ce que demande la question. Il est pris en charge par tous les navigateurs prenant en charge la disposition de la grille .

#container {
  grid-template-columns: 240px 1fr;
  display: grid;
}

#container.reverse {
  direction: rtl;
}

.a {
  background: yellow;
}

.b {
  background: blue;
  color: white;
}
<h3>direction: unset</h3>
<div id="container">
  <div class="a">A</div>
  <div class="b">B</div>
</div>

<h3>direction: rtl</h3>
<div id="container" class="reverse">
  <div class="a">A</div>
  <div class="b">B</div>
</div>
8

J'ai découvert: je dois postuler grid-auto-flow: dense; sur le conteneur:

#container {
  grid-template-columns: 240px 1fr;
  display: grid;
  grid-auto-flow: dense;
}

Selon MDN , cet algorithme tente de combler les trous plus tôt dans la grille.

1
Rob