Posicione o último item flexível no final do contêiner

105

Esta questão se refere a um navegador com suporte total a CSS3, incluindo flexbox.

Eu tenho um contêiner flexível com alguns itens nele. Eles são todos justificados para flex-start, mas quero que o último .end item seja justificado para flex-end. Existe uma boa maneira de fazer isso sem modificar o HTML e sem recorrer ao posicionamento absoluto?

.container {
  display: flex;
  flex-direction: column;
  outline: 1px solid green;
  min-height: 400px;
  width: 100px;
  justify-content: flex-start;
}
p {
  height: 50px;
  background-color: blue;
  margin: 5px;
}
<div class="container">
  <p></p>
  <p></p>
  <p></p>
  <p class="end"></p>
</div>

George Mauer
fonte
2
Sim. Veja as autoilustrações de margem aqui: stackoverflow.com/a/33856609/3597276
Michael Benjamin
Possível duplicata de Alinhar um elemento ao fundo com flexbox
mfluehr

Respostas:

219

Módulo de Layout de Caixa Flexível - 8.1. Alinhando com margens automáticas

Margens automáticas em itens flexíveis têm um efeito muito semelhante às margens automáticas no fluxo de blocos:

  • Durante os cálculos de bases flexíveis e comprimentos flexíveis, as margens automáticas são tratadas como 0.

  • Antes do alinhamento via justify-contente align-self, qualquer espaço livre positivo é distribuído para as margens automáticas nessa dimensão.

Portanto, você pode usar margin-top: autopara distribuir o espaço entre os outros elementos e o último elemento.

Isso posicionará o último elemento na parte inferior.

p:last-of-type {
  margin-top: auto;
}

exemplo vertical


Da mesma forma, você também pode usar margin-left: autoou margin-right: autopara o mesmo alinhamento horizontal.

p:last-of-type {
  margin-left: auto;
}

exemplo horizontal

Josh Crozier
fonte
1
ah perfeito, não acredito que perdi isso! Especialmente embaraçoso, já que eu conheço totalmente o truque do uso de margem automática para centralizar verticalmente e o uso o tempo todo
George Mauer
1
@ j08691 Não tenho uma explicação formal de por que funciona, mas é semelhante a como você pode usar margin: 0 autopara centralização horizontal. Os itens flexbox respeitam a margem, e acredito que margin: autobasicamente posicionarão o item com o máximo de espaço possível entre o irmão. Consulte: w3.org/TR/css-flexbox-1/#auto-margins
Josh Crozier
2
@ jo8691 se não me engano, margin: autoem um item flexível diz para criar o máximo de espaço possível nessa direção.
George Mauer
1
A especificação diz Prior to alignment via justify-content and align-self, any positive free space is distributed to auto margins in that dimension.
George Mauer
Estou tentando aprender mais sobre o flexbox, então seria ótimo ver uma referência que descreve esse comportamento. Particularmente, isso também é intencional e não uma peculiaridade ou efeito colateral.
j08691
61

Este princípio do flexbox também funciona horizontalmente

Durante os cálculos de bases flexíveis e comprimentos flexíveis, as margens automáticas são tratadas como 0.
Antes do alinhamento via justify-content e align-self, qualquer espaço livre positivo é distribuído para as margens automáticas naquela dimensão.

Definir uma margem esquerda automática para o último item fará o trabalho.

.last-item {
  margin-left: auto;
}

Exemplo de código:

.container {
  display: flex;
  width: 400px;
  outline: 1px solid black;
}

p {
  height: 50px;
  width: 50px;
  margin: 5px;
  background-color: blue;
}

.last-item {
  margin-left: auto;
}
<div class="container">
  <p></p>
  <p></p>
  <p></p>
  <p class="last-item"></p>
</div>

Snippet de Codepen

Isso pode ser muito útil para rodapés de área de trabalho.

Como a Envato fez aqui com o logotipo da empresa.

Snippet de Codepen

David Ben Dahan
fonte
3
Não sei por que isso realmente funciona, mas me ajudou em um projeto.
Louis345
4
E se eu precisar que todos os itens fiquem no centro e o último no lado direito?
Illorian