262 votes

Centrer un élément flexbox et aligner les autres à droite et à gauche

J'aimerais avoir A B y 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

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/

370voto

Michael_B Points 15556

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

  • Positionnement CSS
  • Flexbox avec un élément DOM invisible
  • Flexbox avec Pseudo-élément invisible
  • Flexbox avec flex: 1
  • Grille CSS

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

Appliquer position: relative au conteneur flex.

Appliquer position: absolute au point D.

Cet élément est maintenant positionné de manière absolue dans le conteneur flex.

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

Utiliser les propriétés de décalage CSS top y right pour mettre 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 peuvent ne pas supprimer complètement un élément flex absolument positionné du flux normal. Cela modifie l'alignement d'une manière non standard et inattendue. Plus de détails : L'élément flex absolument positionné n'est pas supprimé du flux normal dans IE11


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

Avec une combinaison de auto marges et un nouvel élément de flexion invisible peut être obtenu.

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

Plus précisément, comme l'alignement flexible est basé sur la distribution de l'espace libre, le nouvel élément est un contrepoids nécessaire pour maintenir les trois boîtes du milieu centrées horizontalement. Le nouvel élément doit être de la même largeur que l'élément D existant, sinon les cases du milieu ne seront pas centrées avec précision.

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

En bref :

  • Créer un duplicata du D élément.
  • Placez-la au début de la liste.
  • Utiliser la flexion auto marges à conserver A , B y C centré, avec les deux D créant ainsi un équilibre entre les deux parties.
  • 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 n° 3 : marges automatiques et élément flexible invisible (pseudo-élément)

Cette méthode est similaire à la méthode n°2, sauf qu'elle est plus propre d'un point de vue sémantique et que la largeur de l'élément D doit être connue.

  • Créer un pseudo-élément de même largeur que D .
  • Le placer au début du conteneur avec ::before .
  • Utiliser la flexion auto marges à conserver A , B y C parfaitement centré, avec les pseudo et D créant ainsi un équilibre entre les deux parties.

    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 vers les éléments de gauche et de droite

En commençant par la méthode n° 2 ou n° 3 ci-dessus, au lieu de se préoccuper de la largeur égale des éléments de gauche et de droite pour maintenir l'équilibre, il suffit de donner à chacun d'eux flex: 1 . Cela les obligera à consommer tous les deux 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 peut-être d'autres navigateurs, la règle abrégée est la suivante flex: 1 se résume à ceci :

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

Cela unité de pourcentage (%) en flex-basis entraîne l'interruption de cette méthode lorsque min-height est utilisé sur le conteneur. En effet, en règle générale, les hauteurs en pourcentage sur les enfants requièrent un height sur le parent.

Il s'agit d'une ancienne règle CSS datant de 1998 ( CSS niveau 2 ), qui est toujours en vigueur dans de nombreux navigateurs, à un degré ou à un autre. Pour plus de détails, voir aquí y aquí .

Voici une illustration du problème postée dans les commentaires par utilisateur2651804 :

#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 rien du tout ( ce qui correspond à la recommandation de la spécification 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 : Grille CSS

C'est peut-être la méthode la plus propre et la plus efficace. Il n'est pas nécessaire de recourir au positionnement absolu, à de faux éléments ou à d'autres astuces.

Il suffit de créer une grille avec plusieurs colonnes. Placez ensuite vos articles dans les colonnes du milieu et de la fin. En fait, 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>

1 votes

Très bien, merci pour l'explication ! Je pense que les extraits de code nouvellement ajoutés bénéficieraient d'un raccourcissement du texte de l'exemple, car il n'est pas évident de savoir si le contenu est centré ou non centré en raison de la taille réduite de l'écran. Moi seul ?

0 votes

"Le nouvel élément doit être de la même largeur que l'élément D existant, sinon les cases du milieu ne seront pas centrées avec précision." - c'est dommage qu'il faille que la largeur soit la même, mais merci pour la grille CSS :)

0 votes

En utilisant la technique de la grille, les éléments ne sont pas au centre. Existe-t-il un moyen de faire en sorte que le logo soit au centre ? imgur.com/a/SVg9xsj

32voto

Suhail AKhtar Points 573

La solution la plus simple consiste à justifier le contenu au centre du conteneur parent et à donner une marge gauche automatique au premier et au dernier élément enfant.

ul {
  display:flex;
  justify-content:center;
}

.a,.d {
  margin-left:auto;
}

<ul>
  <li class="a">A</li>
  <li>B</li>
  <li>C</li>
  <li class="d">D</li>
</ul>

0 votes

Ne fonctionne pas pour moi

0 votes

@RedGuy11 pouvez-vous nous dire ce que vous avez fait ?

0 votes

Malheureusement, le programme A/B/C sera axé sur la restant de l'espace par cette méthode. En d'autres termes, même s'il y a de la place pour qu'ils soient centrés par rapport à la largeur totale, ils ne le seront pas.

9voto

Razib Hossain Points 420

Le moyen le plus simple

.box{
  display:flex;
  justify-content:center;
}
.item1{
   flex:1;
   display: flex;
   justify-content: center;
   transform: translateX(10px);/*D element Width[if needed]*/
}

 <div class="box">
   <div class="item1">
      <div>A</div>
      <div>B</div>
      <div>C</div>
   </div>
   <div class="item2">D</div>
 </div>

4 votes

La nécessité d'utiliser la largeur exacte en px de l'élément pourrait être problématique.

2voto

Steven Spungin Points 5660

L'utilisation de la display:grid vous pouvez simplement mettre tous les 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;
}

<div class='ul'>
  <span>
     <span class='li'>A</span>
     <span class='li'>B</span>
     <span class='li'>C</span>
  </span>
  <span class='li'>D</span>
</div>

1 votes

Ce n'est pas du HTML valide (selon les spécifications du W3C/WHATWG) : <span> ne permet que de formuler le contenu, et <ul> ne permet que <li> , <script> o <template> .

0 votes

@cdoublev J'ai changé ul y li à des divs avec des classes pour les rendre valides.

1voto

Ali Korkmaz Points 99

Si vous souhaitez l'aligner, il vous suffit d'attacher une travée vide et d'y répartir les trois travées enfant.

4 votes

Pouvez-vous fournir une courte démonstration pour étayer votre affirmation ?

0 votes

N'utilisez pas le code HTML supplémentaire uniquement pour obtenir une certaine apparence, car il peut endommager votre page dans d'autres navigateurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X