Centro y parte inferior-alinear elementos flexibles


Tengo un contenedor flexible (el cuadrado azul) con las siguientes propiedades:

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

Por lo tanto, sus hijos (los cuadrados azules claros) se ordenan como se ve a continuación. Sin embargo, me gustaría agregar otro niño (el cuadrado verde) fuera del flujo normal y colocarlo en relación con su padre. Para posicionarlo como ves a continuación, idealmente escribiría algo como bottom: 20px; y margin: auto;.

introduzca la descripción de la imagen aquí

Traté de jugar con z-index en vano. ¿Cómo debo acercarme ¿esto? Debo recurrir a la creación de otro elemento padre?

Author: Michael_B, 2016-03-24

3 answers

A continuación se presentan cinco opciones para lograr este diseño:

  1. Posicionamiento CSS
  2. Flexbox con Elemento DOM Invisible
  3. Flexbox con Pseudo-Elemento Invisible
  4. Flexbox con flex: 1
  5. Diseño de cuadrícula CSS

Método #1: Propiedades de posicionamiento CSS

Aplicar position: relative al contenedor flex.

Aplicar position: absolute al elemento verde flexible.

Ahora el cuadrado verde está absolutamente posicionado dentro de la flexión contenedor.

Más específicamente, el cuadrado verde se elimina del flujo del documento, pero permanece dentro de los límites de la antepasado posicionado más cercano.

Utilice las propiedades de desplazamiento CSS top, bottom, left y right para mover el cuadrado verde alrededor.

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>

Una advertencia: Algunos navegadores pueden no eliminar completamente un elemento flex absolutamente posicionado del flujo normal. Esto cambia la alineación en un no estándar, forma inesperada. Más detalles: El elemento flex absolutamente posicionado no se elimina del flujo normal en Firefox e IE11


Método #2: Márgenes Automáticos Flexibles y Elemento Flexible Invisible (elemento DOM)

Con una combinación de auto márgenes y un nuevo elemento flexible invisible se puede lograr el diseño.

El nuevo elemento flex es idéntico al elemento inferior y se coloca en el extremo opuesto (la parte superior).

Más específicamente, debido a que la alineación flexible se basa en la distribución del espacio libre, el nuevo elemento es un contrapeso necesario para mantener las tres cajas azules centradas verticalmente. El nuevo elemento debe tener la misma altura que el elemento verde existente, o las casillas azules no estarán centradas con precisión.

El nuevo elemento se elimina de la vista con visibility: hidden.

En resumen:

  • Cree un duplicado del cuadro verde.
  • Colóquelo al principio de la lista.
  • Use flex auto márgenes para mantener las cajas azules centradas, con ambas cajas verdes creando un equilibrio igual desde ambos extremos.
  • Aplicar visibility: hidden al cuadro verde duplicado.

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étodo # 3: Márgenes Automáticos Flexibles y Elemento Flexible Invisible (pseudo-elemento)

Este método es similar al #2, excepto que es semánticamente más limpio y la altura de la caja verde debe ser conocida.

  • Crear un pseudo-elemento con la misma altura que el existente caja verde.
  • Colóquelo al comienzo del recipiente con ::before.
  • Use márgenes flex auto para mantener las cajas azules centradas, con los elementos pseudo y DOM verdes creando un equilibrio igual desde ambos extremos.

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étodo # 4: Añadir flex: 1 a los elementos superior e inferior

Comenzando con el Método #2 o #3 anterior, en lugar de preocuparse por la misma altura para los elementos superiores e inferiores para mantener el equilibrio igual, simplemente dé a cada uno flex: 1. Esto obligará a ambos a consumir espacio disponible, centrando así el elemento central.

Luego puede agregar display: flex al elemento inferior para alinear el contenido.


Método # 5: Diseño de cuadrícula CSS

Este puede ser el método más limpio y eficiente. No hay necesidad de posicionamiento absoluto, elementos falsos u otro hacker.

Simplemente crea una cuadrícula con tres filas. Luego, alinee los elementos en la segunda y tercera filas. La primera fila puede permanece vacío.

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
Author: Michael_B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-21 22:16:27

Deje el recipiente con position: relative y el cuadrado verde con 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
Author: freestock.tk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 05:03:59

Puede usar un pseudo para mover una fila hacia abajo los primeros tres contenedores y luego aplicar un margin:auto al último

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
Author: G-Cyr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 01:22:16