web-dev-qa-db-fra.com

Éléments flexibles centrés et alignés en bas

J'ai un conteneur flexible (le carré bleu) avec les propriétés suivantes:

display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;

Par conséquent, ses enfants (les carrés bleu clair) s'organisent comme vous le voyez ci-dessous. Cependant, je voudrais ajouter un autre enfant (le carré vert) hors du flux normal et le positionner par rapport à son parent. Pour le positionner comme vous le voyez ci-dessous, j'écrirais idéalement quelque chose comme bottom: 20px; et margin: auto;.

enter image description here

J'ai essayé de jouer avec z-index en vain. Comment dois-je aborder cela? Dois-je recourir à la création d'un autre élément parent?

25
Willege

Voici cinq options pour réaliser cette disposition:

  1. Positionnement CSS
  2. Flexbox avec élément DOM invisible
  3. Flexbox avec pseudo-élément invisible
  4. Flexbox avec flex: 1
  5. Disposition de la grille CSS

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

Appliquez position: relative Au conteneur flexible.

Appliquez position: absolute À l'élément flexible vert.

Maintenant, le carré vert est absolument positionné dans le conteneur flexible.

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

Utilisez les propriétés de décalage CSS top, bottom, left et right pour déplacer le carré vert.

flex-container {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: nowrap;
  position: relative;
  border: 4px solid blue;
  height: 300px;
  width: 300px;
}
flex-container > flex-item:first-child {
  display: flex;
}
flex-container > flex-item:first-child > flex-item {
  border: 4px solid aqua;
  height: 50px;
  width: 50px;
  margin: 0 5px;
}
flex-container > flex-item:last-child {
  position: absolute;
  bottom: 40px;
  left: 50%;
  transform: translateX(-50%); /* fine tune horizontal centering */
  border: 4px solid chartreuse;
  height: 50px;
  width: 50px;
}
<flex-container>
    <flex-item><!-- also flex container -->
            <flex-item></flex-item>
            <flex-item></flex-item>
            <flex-item></flex-item>
    </flex-item>
    <flex-item></flex-item>
</flex-container>

Une mise en garde: 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 Firefox et IE11


Méthode n ° 2: Flex Auto Margins & Invisible Flex Item (élément DOM)

Avec une combinaison de (auto marges et d'un nouvel élément flexible invisible, la mise en page peut être réalisée.

Le nouvel élément flexible est identique à l'élément inférieur et est placé à l'extrémité opposée (le haut).

Plus précisément, parce que l'alignement flexible est basé sur la répartition de l'espace libre, le nouvel élément est un contrepoids nécessaire pour garder les trois cases bleues centrées verticalement. Le nouvel élément doit avoir la même hauteur que l'élément vert existant, sinon les cases bleues 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 la boîte verte.
  • Placez-le au début de la liste.
  • Utilisez les marges flex auto pour garder les cases bleues centrées, les deux cases vertes créant un équilibre égal des deux côtés.
  • Appliquez visibility: hidden À la boîte verte en double.
flex-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    border: 4px solid blue;
    height: 300px;
    width: 300px;
}
flex-container > flex-item:first-child {
    margin-top: auto;
    visibility: hidden;
}
flex-container > flex-item:nth-child(2) {
    margin-top: auto;
    display: flex;
}
flex-container > flex-item:last-child {
    margin-top: auto;
    margin-bottom: auto;
}
flex-container > flex-item:first-child,
flex-container > flex-item:last-child {
    border: 4px solid chartreuse;
    height: 50px;
    width: 50px;
}
flex-container > flex-item:nth-child(2) > flex-item {
    border: 4px solid aqua;
    height: 50px;
    width: 50px;
    margin: 0 5px;
}
<flex-container>
    <flex-item></flex-item>
    <flex-item><!-- also flex container -->
            <flex-item></flex-item>
            <flex-item></flex-item>
            <flex-item></flex-item>
    </flex-item>
    <flex-item></flex-item>
</flex-container>

Méthode n ° 3: Flex Auto Margins & Invisible Flex Item (pseudo-élément)

Cette méthode est similaire à la n ° 2, sauf qu'elle est plus propre sémantiquement et que la hauteur de la boîte verte doit être connue.

  • Créez un pseudo-élément de la même hauteur que la boîte verte existante.
  • Placez-le au début du conteneur avec ::before.
  • Utilisez les marges flex auto pour garder les cases bleues centrées, les éléments pseudo et DOM verts créant un équilibre égal des deux côtés.
flex-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    border: 4px solid blue;
    height: 300px;
    width: 300px;
}
flex-container::before {
  content: "";
  margin-top: auto;
  height: calc(50px + 8px);  /* height + borders */
  visibility: hidden;
}
flex-container > flex-item:first-child {
  margin-top: auto;
  display: flex;
}
flex-container > flex-item:last-child {
  margin-top: auto;
  margin-bottom: auto;
  border: 4px solid chartreuse;
  height: 50px;
  width: 50px;
}
flex-container > flex-item:first-child > flex-item {
  border: 4px solid aqua;
  height: 50px;
  width: 50px;
  margin: 0 5px;
}
<flex-container>
    <flex-item><!-- also flex container -->
        <flex-item></flex-item>
            <flex-item></flex-item>
            <flex-item></flex-item>
    </flex-item>
    <flex-item></flex-item>
</flex-container>

Méthode n ° 4: ajoutez flex: 1 Aux éléments supérieur et inférieur

En commençant par la méthode n ° 2 ou n ° 3 ci-dessus, au lieu de vous soucier de la même hauteur pour les éléments supérieur et inférieur afin de maintenir un équilibre égal, donnez simplement chacun flex: 1. Cela les obligera tous deux à consommer de l'espace disponible, centrant ainsi l'élément du milieu.

Vous pouvez ensuite ajouter display: flex À l'élément inférieur afin d'aligner le contenu.


Méthode n ° 5: disposition de la grille CSS

Cela 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 autre piratage.

Créez simplement une grille avec trois rangées. Centrez ensuite les éléments dans les deuxième et troisième rangées. La première ligne peut rester vide.

grid-container {
  display: grid;
  grid-template-rows: repeat(3, 1fr);
  align-items: center;
  justify-items: center;
  border: 4px solid blue;
  height: 300px;
  width: 300px;
}

grid-item:nth-child(2) {
  display: flex;
}

grid-item:nth-child(2)>flex-item {
  width: 50px;
  height: 50px;
  margin: 0 5px;
  border: 4px solid aqua;
}

grid-item:nth-child(3) {
  border: 4px solid chartreuse;
  height: 50px;
  width: 50px;
}
<grid-container>
  <grid-item></grid-item>
  <grid-item><!-- also flex container -->
    <flex-item></flex-item>
    <flex-item></flex-item>
    <flex-item></flex-item>
  </grid-item>
  <grid-item></grid-item>
</grid-container>
45
Michael_B

laissez le conteneur avec position: relative et le carré vert avec position:absolute;

body {
  margin: 0;  
}

#container {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: nowrap;
  width: 192px;
  height: 192px;
  border: 4px solid Indigo;
  position: relative;
  background: lavender;
}

.blue {
  margin: 10px;
  width: 30px;
  height: 30px;
  outline: 4px solid skyblue;
  background: honeydew;
}

#green {
  position: absolute;
  width: 30px;
  height: 30px;
  left: 0;
  right: 0;
  margin: auto;
  bottom: 20px;
  outline: 4px solid yellowgreen;
  background: greenyellow;
}
<div id=container>
<div class=blue></div><div class=blue></div><div class=blue></div>
<div id=green></div>
</div>
4
Le____

vous pouvez utiliser un pseudo pour descendre d'une ligne les trois premiers conteneurs puis appliquer un margin:auto au dernier

div {
  display:flex;
  flex-wrap:wrap;
  border:#0066FD solid;;
  width:200px;
  height:200px;
  justify-content:space-around;
  /* show me box center */
  background:linear-gradient(to top,rgba(0,0,0,0.2) 50%, transparent 50%),linear-gradient(to left,rgba(0,0,0,0.2) 50%, transparent 50%)
 
}

span, div:before {
  width:50px;
  height:50px;
  border:solid #01CDFF;
  margin:0 auto 0;
}
span:last-of-type , div:before{
  margin: 12px auto;
  border:solid  #01FE43;
}
div:before {
  content:'';
  width:100%;
  border:none;
}

span {
   /* show me box center */
  background:linear-gradient(45deg,rgba(0,0,0,0.1) 50%, transparent 50%),linear-gradient(-45deg,rgba(0,0,0,0.1) 50%, transparent 50%)
  }
<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>
3
G-Cyr