Desafio e limitação do Flexbox
O desafio é centralizar um grupo de itens flexíveis e alinhá-los à esquerda na embalagem. Mas, a menos que haja um número fixo de caixas por linha e cada caixa tenha largura fixa, isso não é possível com o flexbox.
Usando o código postado na pergunta, poderíamos criar um novo flex container que envolvesse o flex container atual ( ul
), o que nos permitiria centralizar ul
com justify-content: center
.
Em seguida, os itens flexíveis do ul
podem ser alinhados à esquerda com justify-content: flex-start
.
#container {
display: flex;
justify-content: center;
}
ul {
display: flex;
justify-content: flex-start;
}
Isso cria um grupo centralizado de flex items alinhados à esquerda.
O problema com esse método é que em certos tamanhos de tela haverá uma lacuna à direita do ul
, fazendo com que ele não pareça mais centralizado.
Isso acontece porque no layout flexível (e, na verdade, CSS em geral) o contêiner:
- não sabe quando um elemento é encerrado;
- não sabe que um espaço anteriormente ocupado agora está vazio, e
- não recalcula sua largura para reduzir o layout mais estreito.
O comprimento máximo do espaço em branco à direita é o comprimento do flex item que o contêiner esperava estar lá.
Na demonstração a seguir, redimensionando a janela horizontalmente, você pode ver o espaço em branco ir e vir.
DEMO
Uma abordagem mais prática
O layout desejado pode ser alcançado sem flexbox usando inline-block
e consultas de mídia .
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; } }
O código acima renderiza um contêiner centralizado horizontalmente com elementos filho alinhados à esquerda como este:
DEMO
Outras opções
margin:0 auto
em um wrapper pai, de modo que tudo fique centralizado na página. A partir desse ponto, todos os componentes filhos, (ou seja, o primeiro flex-container) passam pelo processo de linha de fluxo normal? Parece que isso poderia ser simplificado de fazer.Você pode conseguir isso com CSS Grid, basta usar
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/
fonte
justify-items: center
parajustify-content:center
e agora está centralizado perfeitamente.210px
parte internaminmax
. Como faço para fazer o mesmo, mas sem uma restrição artificial de210px
? Não existe essa restrição com o flexbox. Eu quero exatamente o mesmo resultado do flexbox, mas a área de conteúdo deve estar centralizada como na sua solução.width:200px
, e no meu exemplo, conforme eu definiwidth:210px
, eu tenho que adicionar isso também naminmax
parteComo @michael sugeriu, esta é uma limitação do flexbox atual. Mas se você ainda quiser usar
flex
ejustify-content: center;
, podemos contornar isso adicionando umli
elemento fictício e atribuirmargin-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 violino (redimensionar e ver) ou vídeo para referência
fonte
Uma maneira de obter o estilo desejado com margens é fazer o seguinte:
#container { display: flex; justify-content: center; } #innercontainer { display: flex; flex: 0.9; -> add desired % of margin justify-content: flex-start; }
fonte
Você pode colocar elementos invisíveis com a mesma classe dos demais (retirados no exemplo para fins de exibição) e altura configurada para 0. Com isso, você poderá justificar os itens logo no início da grade.
Exemplo
<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
fonte
Eu estava enfrentando um problema semelhante ao tentar centralizar o conteúdo dentro do flex. Tentei vários truques e consertos, mas não estava funcionando por causa de um erro bobo.
Se alguém que vem aqui não consegue contornar o problema mesmo depois de ler essas respostas, tente verificar se há erros bobos. No meu caso, foi um
span
comflex-grow
conjunto para1
adicionado como um espaçador.fonte
Eu tive esse problema ao codificar com o React Native. Existe uma solução elegante que você pode ter usando o FlexBox. Na minha situação particular, eu estava tentando centralizar três caixas flex (Flex: 2) dentro de outra usando alignItems. A solução que encontrei foi usar dois s vazios, cada um com Flex: 1.
<View style={{alignItems: 'center', flexWrap: 'wrap', flexDirection: 'row'}}> <View style={{flex: 1}} /> // Content here <View style={{flex: 1}} /> </View>
Fácil de converter para web / CSS.
fonte