Centre et bas-alignent les éléments flex

j'ai un conteneur souple (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 voyez ci-dessous. Cependant, j'aimerais 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 devrais-je m'approche de cela? Dois-je recourir à la création d'un autre élément parent?

24
demandé sur Michael_B 2016-03-24 04:04:51

3 réponses

on trouvera ci-dessous cinq options pour réaliser cette disposition:

  1. Positionnement CSS
  2. Flexbox avec élément DOM Invisible
  3. Flexbox avec un Pseudo-élément Invisible
  4. Flexbox avec flex: 1
  5. Grille CSS de Mise en page

méthode no 1: Propriétés de positionnement CSS

appliquer position: relative au conteneur souple.

Appliquer position: absolute au vert flex élément.

maintenant le carré vert est absolument positionné dans le conteneur flex.

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

utiliser les propriétés d'offset CSS top , bottom , left et right pour déplacer le carré vert autour.

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 positionné absolument du flux normal. Cela change l'alignement d'une manière non standard et inattendue. Plus de détails: absolument l'article flex positionné N'est pas retiré de l'écoulement normal en Firefox & IE11


Méthode #2: Flex Auto Margins & Invisible Flex Item (DOM element)

avec une combinaison de auto marges et un nouvel élément flex invisible la mise en page peut être réalisée.

le nouvel article flex est identique à l'article du bas et est placé à l'extrémité opposée (le haut).

plus spécifiquement, parce que l'alignement flex est basé sur la distribution de l'espace libre, le nouvel article est un contrepoids nécessaire pour garder les trois boîtes bleues verticalement centrées. Le nouvel article doit avoir la même hauteur que l'article Vert existant, sinon les boîtes bleues ne seront pas exactement centrées.

le nouvel article est supprimé de la vue avec visibility: hidden .

en bref:

  • boîte verte.
  • le Placer au début de la liste.
  • utilisez flex auto marges pour garder les boîtes bleues centrées, avec les deux boîtes vertes créant l'équilibre égal des deux extrémités.
  • appliquer 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 #3: Flex Auto Margins & Invisible Flex Item (pseudo-élément)

cette méthode est similaire à la méthode #2, sauf qu'elle est plus propre sur le plan sémantique et que la hauteur de la boîte verte doit être connue.

  • créer un pseudo-élément avec la même hauteur que la boîte verte existante.
  • le placer au début du conteneur avec ::before .
  • utilisez flex auto marges pour garder les boîtes bleues centrées, avec les éléments verts pseudo et DOM créer 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 No 4: Ajouter flex: 1 aux éléments supérieurs et inférieurs

en commençant par la méthode #2 ou #3 ci-dessus, au lieu de s'inquiéter d'une hauteur égale pour les éléments supérieurs et inférieurs pour maintenir un équilibre égal, il suffit de donner à chacun flex: 1 . Cela les forcera tous les deux à consommer l'espace disponible, centrant ainsi le milieu article.

vous pouvez alors ajouter display: flex à l'article du bas afin d'aligner le contenu.


méthode no 5: disposition de la grille CSS

C'est peut-être le plus propre et la plus efficace. Il n'y a pas besoin de positionnement absolu, de faux éléments ou d'autres hackery.

il suffit de créer une grille avec trois lignes. Le centre-aligner 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>
44
répondu Michael_B 2017-09-21 22:16:27

laisser 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
répondu freestock.tk 2016-03-24 05:03:59

vous pouvez utiliser un pseudo pour se déplacer vers le bas d'une rangée les trois premiers conteneurs puis appliquer un margin:auto à la dernière

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
répondu G-Cyr 2016-03-24 01:22:16