Je voudrais avoir A
B
et C
alignés au milieu.
Comment puis-je obtenir D
pour aller complètement à droite?
AVANT:
APRÈS:
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>
Voici cinq options pour réaliser cette mise en page:
flex: 1
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
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:
D
.auto
pour maintenir A
, B
et C
centrés, les deux éléments D
créant un équilibre égal des deux côtés.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>
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.
D
.::before
.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>
flex: 1
aux éléments gauche et droitEn 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>
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>
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;
}
Si vous souhaitez l'aligner, vous pouvez simplement attacher une étendue vide et diviser les trois étendues enfants en elles.
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>
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>