Desafío y limitación de Flexbox
El desafío es centrar un grupo de elementos flexibles y alinearlos a la izquierda en la envoltura. Pero a menos que haya un número fijo de cajas por fila, y cada caja tenga un ancho fijo, esto no es posible actualmente con flexbox.
Usando el código publicado en la pregunta, podríamos crear un nuevo contenedor flexible que envuelva el contenedor flexible actual ( ul
), lo que nos permitiría centrar ul
con justify-content: center
.
Luego, los elementos flexibles del ul
podría alinearse a la izquierda con justify-content: flex-start
.
#container {
display: flex;
justify-content: center;
}
ul {
display: flex;
justify-content: flex-start;
}
Esto crea un grupo centrado de elementos flexibles alineados a la izquierda.
El problema con este método es que en ciertos tamaños de pantalla habrá un espacio a la derecha del ul
, por lo que ya no aparecerá centrado.
Esto sucede porque en el diseño flexible (y, de hecho, CSS en general) el contenedor:
- no sabe cuándo se envuelve un elemento;
- no sabe que un espacio previamente ocupado ahora está vacío, y
- no recalcula su ancho para encoger el diseño más estrecho.
La longitud máxima del espacio en blanco de la derecha es la longitud del elemento flexible que el contenedor esperaba que estuviera allí.
En la siguiente demostración, al cambiar el tamaño de la ventana horizontalmente, puede ver que los espacios en blanco van y vienen.
MANIFESTACIÓN
Un enfoque más práctico
El diseño deseado se puede lograr sin el uso de flexbox inline-block
y las consultas de medios .
HTML
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
CSS
ul {
margin: 0 auto;
width: 1200px;
padding-left: 0;
font-size: 0;
}
li {
display: inline-block;
font-size: 18px;
list-style-type: none;
width: 150px;
height: 50px;
line-height: 50px;
margin: 15px 25px;
box-sizing: border-box;
text-align: center;
}
@media screen and (max-width: 430px) { ul { width: 200px; } }
@media screen and (min-width: 431px) and (max-width: 630px) { ul { width: 400px; } }
@media screen and (min-width: 631px) and (max-width: 830px) { ul { width:600px; } }
@media screen and (min-width: 831px) and (max-width: 1030px) { ul { width: 800px; } }
@media screen and (min-width: 1031px) and (max-width: 1230px) { ul { width: 1000px; } }
El código anterior representa un contenedor centrado horizontalmente con elementos secundarios alineados a la izquierda como este:
MANIFESTACIÓN
Otras opciones
margin:0 auto
en una envoltura principal, para que todo esté centrado en la página. Desde ese punto, ¿todos los componentes secundarios (es decir, el primer contenedor flexible) siguen su proceso de fila de flujo normal? Parece que esto podría simplificarse.Puedes lograrlo con CSS Grid, solo usa
repeat(autofit, minmax(width-of-the-element, max-content))
ul { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, max-content)); grid-gap: 16px; justify-content: center; padding: initial; } li { list-style-type: none; border: 1px solid gray; padding: 5px; width: 210px; }
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> </ul>
http://jsfiddle.net/rwa20jkh/
fuente
justify-items: center
ajustify-content:center
, y ahora se centra perfectamente.210px
parte de adentrominmax
. ¿Cómo puedo hacer lo mismo pero sin una restricción artificial de210px
? No existe tal restricción con flexbox. Quiero exactamente el mismo resultado que con flexbox, pero el área de contenido debe estar centrada como en su solución.width:200px
, y en mi ejemplo, como establecíwidth:210px
, tengo que agregar eso también en laminmax
parteComo sugirió @michael, esta es una limitación con el flexbox actual. Pero si aún desea usar
flex
yjustify-content: center;
, entonces podemos solucionar esto agregando unli
elemento ficticio y asignarmargin-left
.const handleResize = () => { const item_box = document.getElementById('parentId') const list_length = item_box.clientWidth const product_card_length = 200 // length of your child element const item_in_a_row = Math.round(list_length/product_card_length) const to_be_added = item_in_a_row - parseInt(listObject.length % item_in_a_row) // listObject is the total number items const left_to_set = (to_be_added - 1 ) * product_card_length // -1 : dummy item has width set, so exclude it when calculating the left margin const dummy_product = document.querySelectorAll('.product-card.dummy')[0] dummy_product.style.marginLeft = `${left_to_set}px` } handleResize() // Call it first time component mount window.addEventListener("resize", handleResize);
Verifique este violín (cambie el tamaño y vea) o el video como referencia
fuente
Una forma de obtener el estilo deseado con márgenes es hacer lo siguiente:
#container { display: flex; justify-content: center; } #innercontainer { display: flex; flex: 0.9; -> add desired % of margin justify-content: flex-start; }
fuente
Puede colocar elementos invisibles con la misma clase que los demás (eliminados en el ejemplo con fines de exhibición) y la altura establecida en 0. Con eso, podrá justificar los elementos hasta el comienzo de la cuadrícula.
Ejemplo
<div class="table-container"> <div class="table-content"> <p class="table-title">Table 1</p> <p class="mesa-price">$ 20</p> </div> <!-- Make stuff justified start --> <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div> <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div> <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div> <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div> </div>
Resultado
fuente
Me encontré con este problema mientras codificaba con React Native. Existe una solución elegante que puede tener con FlexBox. En mi situación particular, estaba tratando de centrar tres cajas flexibles (Flex: 2) dentro de otra usando alignItems. La solución que se me ocurrió fue usar dos s vacíos, cada uno con Flex: 1.
<View style={{alignItems: 'center', flexWrap: 'wrap', flexDirection: 'row'}}> <View style={{flex: 1}} /> // Content here <View style={{flex: 1}} /> </View>
Bastante fácil de convertir a web / CSS.
fuente