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
- Disposition de la grille CSS
Méthode n ° 1: Propriétés de positionnement CSS
Appliquer position: relative
sur le conteneur flexible.
Appliquer position: absolute
à l'article D.
Cet élément est désormais positionné de manière absolue dans le conteneur flexible.
Plus spécifiquement, l'élément D est supprimé du flux de documents mais reste dans les limites de l' ancêtre positionné 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>
Une mise en garde à 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 non standard et inattendue. Plus de détails: L'élément flex positionné de manière absolue n'est pas supprimé du flux normal dans IE11
Méthode n ° 2: marges automatiques flexibles et élément flexible invisible (élément DOM)
Avec une combinaison de auto
marges et un nouvel élément flexible invisible, la mise en page peut être obtenue.
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, étant donné que l'alignement flexible est basé sur la répartition de l'espace libre, le nouvel élément est un contrepoids nécessaire pour maintenir les trois cases du milieu 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 précisément centrées.
Le nouvel élément est supprimé de la vue avec visibility: hidden
.
En bref:
- Créez un double de l'
D
élément.
- Placez-le au début de la liste.
- Utilisation fléchir les
auto
marges pour maintenir A
, B
et C
centrée, avec les deux D
éléments créant un équilibre égal des deux extrémités.
- Appliquer
visibility: hidden
au duplicataD
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 flexibles et élément flexible invisible (pseudo-élément)
Cette méthode est similaire à # 2, sauf qu'elle est plus sémantique et que la largeur de D
doit être connue.
- Créez un pseudo-élément de même largeur que
D
.
- Placez-le au début du conteneur avec
::before
.
- Utilisez les
auto
marges flexibles pour garder A
, B
et C
parfaitement centré, le pseudo et les D
éléments 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 n ° 4: Ajouter flex: 1
aux éléments de gauche et de droite
En commençant par la méthode n ° 2 ou n ° 3 ci-dessus, au lieu de vous soucier de la largeur égale des éléments gauche et droit pour maintenir un équilibre égal, donnez simplement chacun flex: 1
. Cela les forcera tous les deux à consommer de 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.
REMARQUE 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éeflex: 1
se résume à ceci:
flex-grow: 1
flex-shrink: 1
flex-basis: 0%
Cette unité de pourcentage (%) sur flex-basis
provoque la rupture de cette méthode lorsqu'elle min-height
est utilisée sur le conteneur. En effet, en règle générale, les hauteurs en pourcentage sur les enfants nécessitent un height
paramètre de propriété explicite 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 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 ( c'est ce que la spécification recommande en fait , 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: disposition 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 d'autres piratages.
Créez simplement une grille avec plusieurs colonnes. Positionnez ensuite vos articles dans les colonnes du milieu et de la fin. En gros, laissez simplement 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>