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>