Éléments de flexbox de Centre et de droite

j'aimerais que A B et C soient alignés au milieu.

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

avant:

enter image description here

après:

enter image description here

Quelle est la meilleure pratique pour faire 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 /

43
demandé sur Michael_B 2016-08-15 04:13:17

2 réponses

vous trouverez ci-dessous cinq options pour réaliser cette mise en page:

  • Positionnement CSS
  • Flexbox avec élément DOM Invisible
  • Flexbox avec un Pseudo-élément Invisible
  • Flexbox avec flex: 1
  • Grille CSS de Mise en page

méthode no 1: Propriétés de positionnement CSS

appliquer position: relative au conteneur souple.

appliquer position: absolute à L'article D.

maintenant cet article est absolument positionné dans le conteneur flex.

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

utiliser les propriétés d'offset CSS top et right pour mettez 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>

Une mise en garde de cette méthode est que certains navigateurs ne peuvent pas supprimer complètement un positionnement absolu flex élément dans le flux normal. Cela change l'alignement d'une manière non standard et inattendue. Plus de détails: L'article Flex positionné absolument n'est pas enlevé du flux normal dans IE11


Méthode #2: Flex Auto Margins & Invisible Flex Item (DOM element)

avec une combinaison de auto marges et un nouvel élément flex invisible la disposition peut être réalisée.

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

plus spécifiquement, parce que flex l'alignement est basé sur la distribution de l'espace libre, le nouvel élément est un contrepoids nécessaire de garder les trois boîtes moyennes centrée horizontalement. Le nouvel élément doit avoir la même largeur que L'élément D existant, sinon les boîtes du milieu ne seront pas exactement centrées.

le nouvel article est supprimé de la vue avec visibility: hidden .

en bref:

  • créer un duplicata de l'élément D .
  • le Placer au début de la liste.
  • utilisez flex auto marges pour garder A , B et C centré, avec les deux D éléments créant l'équilibre égal des deux extrémités.
  • appliquer visibility: hidden au duplicata 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 No 3: Marges Automatiques Flex & Invisible Flex Élément (pseudo-élément)

cette méthode est similaire à la méthode #2, sauf qu'elle est plus propre sur le plan sémantique et que la largeur de D doit être connue.

  • Créer un pseudo-élément avec la même largeur que D .
  • le placer au début du conteneur avec ::before .
  • utilisez flex auto marges pour conserver A , B et C parfaitement centré, avec les éléments pseudo et D créant un équilibre égal des deux extrémité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 No 4: Ajouter flex: 1 à gauche et à droite

en commençant par la méthode #2 ou #3 ci-dessus, au lieu de s'inquiéter de la largeur égale pour les articles de gauche et de droite pour maintenir l'équilibre, il suffit de donner à chacun flex: 1 . Cela va forcer les deux pour consommer l'espace disponible, centrant ainsi l'élément du milieu.

vous pouvez alors ajouter display: flex à des articles individuels afin d'aligner leur contenu.

NOTE à propos de l'utilisation de cette méthode avec min-height : actuellement dans les navigateurs Chrome, Firefox, Edge et peut-être d'autres, la règle sténodale flex: 1 se décompose en ceci:

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

que Unité de pourcentage ( % ) sur flex-basis provoque la rupture de cette méthode lorsque min-height est utilisé sur le conteneur. Cela est dû au fait que, en règle générale, les pourcentages de hauteur sur les enfants exigent un height propriété explicite sur le parent.

c'est une vieille règle CSS datant retour à 1998 ( CSS Level 2 ) qui est encore en vigueur dans de nombreux navigateurs à un certain degré ou un autre. Pour plus de détails, voir ici et ici .

voici une illustration du problème posté 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 est de ne pas utiliser l'Unité de pourcentage. Essayez px ou tout simplement rien du tout ( qui est ce que le spec 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 no 5: disposition de la grille CSS

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

il suffit de créer une grille avec plusieurs colonnes. Ensuite, placez vos articles dans les colonnes du milieu et de la fin. En gros, laissez 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>
74
répondu Michael_B 2018-03-26 22:16:36

question très claire. Je ne pouvais pas m'empêcher de poster la réponse après quelques heures de creuser. Nous avons pu résoudre cela avec des tables, table-cellule, positions absolues, transforme mais nous avons juste eu à le faire avec flexbox :)

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

.center {
  margin: auto;
}

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

2
répondu rgfx 2016-09-12 02:48:32