web-dev-qa-db-fra.com

Aligner les éléments de la flexbox

Je voudrais avoir AB et C alignés au milieu.

Comment puis-je obtenir D pour aller complètement à droite?

AVANT:

 enter image description here

APRÈS:

 enter image description here

Quelle est la meilleure pratique pour cela?

ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  /* magic to throw to the right*/
}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>

https://jsfiddle.net/z44p7bsx/

62
hazyred

Voici cinq options pour réaliser cette mise en page:

  • Positionnement CSS 
  • Flexbox avec élément DOM invisible
  • Flexbox avec pseudo-élément invisible
  • Flexbox avec flex: 1
  • CSS Grid Layout

Méthode n ° 1: Propriétés de positionnement CSS

Appliquez position: relative au conteneur Flex.

Appliquez position: absolute à l'article D.

Maintenant, cet article est absolument positionné dans le conteneur flexible.

Plus précisément, l'élément D est supprimé du flux de documents mais reste dans les limites du ancêtre le plus proche .

Utilisez les propriétés de décalage CSS top et right pour déplacer cet élément en position.

li:last-child {
  position: absolute;
  top: 0;
  right: 0;
  background: #ddd;
}
ul {
  position: relative;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p {
  text-align: center;
  margin-top: 0;
}
span {
  background-color: aqua;
}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>

Un inconvénient de cette méthode est que certains navigateurs peuvent ne pas supprimer complètement un élément flex positionné de manière absolue du flux normal. Cela modifie l'alignement d'une manière inattendue et non standard. Plus de détails: L'élément de flex absolu positionné n'est pas supprimé du flux normal dans IE11


Méthode n ° 2: Marges auto Flex et élément Flex invisible (élément DOM)

Avec une combinaison de auto marges et un nouvel élément flexible invisible, la présentation peut être réalisée.

Le nouvel article flex est identique à l'article D et est placé à l'extrémité opposée (bord gauche).

Plus précisément, l’alignement de la flexion étant basé sur la distribution de l’espace libre, le nouvel élément constitue un contrepoids nécessaire pour que les trois boîtes du milieu soient centrées horizontalement. Le nouvel élément doit avoir la même largeur que l'élément D existant, sinon les cases du milieu ne seront pas exactement centrées.

Le nouvel élément est supprimé de la vue avec visibility: hidden.

En bref:

  • Créez une copie de l'élément D.
  • Placez-le au début de la liste.
  • Utilisez les marges auto pour maintenir A, B et C centrés, les deux éléments D créant un équilibre égal des deux côtés.
  • Appliquer visibility: hidden à la copie D

li:first-child {
  margin-right: auto;
  visibility: hidden;
}
li:last-child {
  margin-left: auto;
  background: #ddd;
}
ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
  <li>D</li><!-- new; invisible spacer item -->
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>


Méthode n ° 3: Marges auto Flex et élément Flex invisible (pseudo-élément)

Cette méthode est similaire à la n ° 2, à la différence que sa propreté est sémantique et que la largeur de D doit être connue.

  • Créez un pseudo-élément ayant la même largeur que D.
  • Placez-le au début du conteneur avec ::before.
  • Utilisez les marges de variation auto pour garder A, B et C parfaitement centrés, les éléments pseudo et D créant un équilibre égal des deux côtés.

ul::before {
  content:"D";
  margin: 1px auto 1px 1px;
  visibility: hidden;
  padding: 5px;
  background: #ddd;
}
li:last-child {
  margin-left: auto;
  background: #ddd;
}
ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>


Méthode n ° 4: Ajouter flex: 1 aux éléments gauche et droit

En commençant par la méthode n ° 2 ou n ° 3 ci-dessus, au lieu de vous soucier d'une largeur égale pour les éléments gauche et droit afin de maintenir un équilibre égal, attribuez simplement à chacun un flex: 1. Cela les obligera tous les deux à utiliser l'espace disponible, centrant ainsi l'élément du milieu.

Vous pouvez ensuite ajouter display: flex à des éléments individuels afin d’aligner leur contenu.

NOTE _ ​​sur l'utilisation de cette méthode avec min-height: Actuellement dans Chrome, Firefox, Edge et éventuellement d'autres navigateurs, la règle abrégée flex: 1 se décompose en ceci:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0%

Cette unité de pourcentage (%) sur flex-basis provoque l'arrêt de cette méthode lorsque min-height est utilisé sur le conteneur. En effet, les hauteurs de pourcentage sur les enfants nécessitent généralement un paramètre de propriété explicite height sur le parent.

Il s'agit d'une ancienne règle CSS datant de 1998 ( CSS niveau 2 ) qui est encore en vigueur dans de nombreux navigateurs. Pour plus de détails, voir ici et ici .

Voici une illustration du problème signalé dans les commentaires de user2651804 :

#flex-container {
  display: flex;
  flex-direction: column;
  background: teal;
  width: 150px;
  min-height: 80vh;
  justify-content: space-between;
}

#flex-container>div {
  background: orange;
  margin: 5px;
}

#flex-container>div:first-child {
  flex: 1;
}

#flex-container::after {
  content: "";
  flex: 1;
}
<div id="flex-container">
  <div>very long annoying text that will add on top of the height of its parent</div>
  <div>center</div>
</div>

La solution consiste à ne pas utiliser l'unité de pourcentage. Essayez px ou tout simplement rien du tout ( ce que la spécification recommande réellement , malgré le fait qu'au moins certains des principaux navigateurs ont ajouté une unité de pourcentage pour une raison quelconque).

#flex-container {
  display: flex;
  flex-direction: column;
  background: teal;
  width: 150px;
  min-height: 80vh;
  justify-content: space-between;
}

#flex-container > div {
  background: orange;
  margin: 5px;
}


/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */

#flex-container > div:first-child {
  flex: 1;
  flex-basis: 0;
}

#flex-container::after {
  content: "";
  flex: 1;
  flex-basis: 0;
}


/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY

#flex-container > div:first-child {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
}

#flex-container::after {
  content: "";
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
}
 */
<div id="flex-container">
  <div>very long annoying text that will add on top of the height of its parent</div>
  <div>center</div>
</div>


Méthode n ° 5: présentation de la grille CSS

C'est peut-être la méthode la plus propre et la plus efficace. Il n'y a pas besoin de positionnement absolu, de faux éléments ou de tout autre hackery.

Créez simplement une grille avec plusieurs colonnes. Placez ensuite vos éléments dans les colonnes du milieu et de la fin. Fondamentalement, il suffit de laisser la première colonne vide.

ul {
  display: grid;
  grid-template-columns: 1fr repeat(3, auto) 1fr;
  grid-column-gap: 5px;
  justify-items: center;
}

li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }

/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p  { text-align: center; }
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>| true center |</span></p>

107
Michael_B

Question très claire. Je ne pouvais pas m'empêcher de poster la réponse après quelques heures de fouilles. Nous aurions pu résoudre ce problème avec des tables, des cellules de table, des positions absolues, des transformations, mais nous devions le faire avec flexbox :)

.parent {
  display: flex;
  justify-content: flex-end;
}

.center {
  margin: auto;
}

http://codepen.io/rgfx/pen/BLorgd

3
rgfx

Si vous souhaitez l'aligner, vous pouvez simplement attacher une étendue vide et diviser les trois étendues enfants en elles.

1
Ali Korkmaz

En utilisant l’approche display:grid, vous pouvez simplement mettre tous les enfants ul dans la même cellule, puis définir justify-self:

ul {
  display: grid;
}

ul > * {
  grid-column-start: 1;
  grid-row-start: 1;
  justify-self:center;
}

ul > *:last-child {
  justify-self: right;
}

/* Make Fancy */
li {
  display:inline-block;
  margin: 1px;
  padding: 5px;
  background: #bbb;
}
<ul>
  <span>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  </span>
  <li>D</li>
</ul>
0
Steven Spungin

J'ai développé sur Michael_B 's répondre

.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3) {
  flex: 1;
}
.center-flex__2-of-3 > :nth-child(1) {
  justify-content: flex-start;
}
.center-flex__2-of-3 > :nth-child(3) {
  justify-content: flex-end;
}
.center-flex__1-of-2 > :nth-child(1) {
  margin: auto;
}
.center-flex__1-of-2 > :nth-child(2) {
  flex: 1;
  justify-content: flex-end;
}
.center-flex__2-of-2 > :nth-child(1) {
  flex: 1;
  justify-content: flex-start;
}
.center-flex__2-of-2 > :nth-child(2) {
  margin: auto;
}
.center-flex__1-of-2:before, .center-flex__1-of-1:before {
  content: '';
  flex: 1;
}
.center-flex__1-of-1:after, .center-flex__2-of-2:after {
  content: '';
  flex: 1;
}

[class*=center-flex] {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  border: 10px solid rgba(0, 0, 0, 0.1);
}
[class*=center-flex] > * {
  display: flex;
}
li {
  padding: 3px 5px;
}
2 of 3
<ul class="center-flex__2-of-3">
  <span>
    <li>Accusamus</li>
    <li>Porro</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

<br><br>
1 of 1
<ul class="center-flex__1-of-1">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

Ici avec l'aide du SASS en tant que codepen

0
yunzen