Alinhar ao centro e à direita elementos flexbox

147

Eu gostaria de ter A Be Calinhado no meio.

Como posso Dir completamente para a direita?

ANTES:

insira a descrição da imagem aqui

DEPOIS DE:

insira a descrição da imagem aqui

ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  /* magic to throw to the right*/
}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>

https://jsfiddle.net/z44p7bsx/

Hazyred
fonte

Respostas:

214

Abaixo estão cinco opções para alcançar esse layout:

  • Posicionamento CSS
  • Flexbox com elemento DOM invisível
  • Flexbox com pseudo-elemento invisível
  • Flexbox com flex: 1
  • Layout de Grade CSS

Método # 1: Propriedades de posicionamento CSS

Aplique position: relativeno recipiente flexível.

Aplique position: absoluteao item D.

Agora este item está absolutamente posicionado dentro do contêiner flexível.

Mais especificamente, o item D é removido do fluxo de documentos, mas permanece dentro dos limites do ancestral posicionado mais próximo .

Use as propriedades de deslocamento CSS tope rightpara mover esse elemento para a posição.

Uma ressalva para esse método é que alguns navegadores podem não remover completamente um item flexível absolutamente posicionado do fluxo normal. Isso altera o alinhamento de maneira inesperada e não padrão. Mais detalhes: O item flexível absolutamente posicionado não é removido do fluxo normal no IE11


Método 2: Margens automáticas flexíveis e item flexível invisível (elemento DOM)

Com uma combinação de automargens e um novo item flexível invisível, o layout pode ser alcançado.

O novo item flexível é idêntico ao item D e é colocado na extremidade oposta (a borda esquerda).

Mais especificamente, como o alinhamento flexível é baseado na distribuição de espaço livre, o novo item é um contrapeso necessário para manter as três caixas do meio centralizadas horizontalmente. O novo item deve ter a mesma largura que o item D existente, ou as caixas do meio não serão centralizadas com precisão.

O novo item é removido da visualização com visibility: hidden.

Em resumo:

  • Crie uma duplicata do Delemento.
  • Coloque-o no início da lista.
  • Uso flectir automargens para manter A, Be Ccentrado, com ambos os Delementos de criar equilíbrio igual a partir de ambas as extremidades.
  • Aplicar visibility: hiddenà duplicataD


Método # 3: Margens automáticas flexíveis e item flexível invisível (pseudoelemento)

Esse método é semelhante ao nº 2, exceto que é mais limpo semanticamente e a largura de Ddeve ser conhecida.

  • Crie um pseudoelemento com a mesma largura que D.
  • Coloque-o no início do recipiente com ::before.
  • Use automargens flexíveis para manter A, Be Cperfeitamente centralizado, com o pseudo e os Delementos criando um equilíbrio igual entre as duas extremidades.


Método 4: Adicionar flex: 1aos itens esquerdo e direito

Começando pelo método nº 2 ou nº 3 acima, em vez de se preocupar com a mesma largura dos itens esquerdo e direito para manter o equilíbrio, basta fornecer cada um flex: 1. Isso forçará os dois a consumir o espaço disponível, centralizando o item do meio.

Você pode adicionar display: flexitens individuais para alinhar seu conteúdo.

NOTA sobre o uso deste método com min-height: Atualmente no Chrome, Firefox, Edge e possivelmente em outros navegadores, a regra abreviada seflex: 1divide em:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0%

Essa unidade de porcentagem (%) ativada flex-basisfaz com que esse método quebre quando min-heighté usado no contêiner. Isso ocorre porque, como regra geral, as alturas de porcentagem nos filhos exigem uma heightconfiguração explícita de propriedade no pai.

Essa é uma regra antiga de CSS que remonta a 1998 ( CSS Nível 2 ), que ainda está em vigor em muitos navegadores, em algum grau ou outro. Para detalhes completos, veja aqui e aqui .

Aqui está uma ilustração do problema postado nos comentários do usuário2651804 :

A solução é não usar a unidade percentual. Tente pxou simplesmente nada (o que a especificação realmente recomenda , apesar do fato de que pelo menos alguns dos principais navegadores acrescentaram uma unidade de porcentagem por qualquer motivo).


Método # 5: Layout da Grade CSS

Esse pode ser o método mais limpo e eficiente. Não há necessidade de posicionamento absoluto, elementos falsos ou outros truques.

Basta criar uma grade com várias colunas. Posicione seus itens nas colunas central e final. Basicamente, basta deixar a primeira coluna vazia.

ul {
  display: grid;
  grid-template-columns: 1fr repeat(3, auto) 1fr;
  grid-column-gap: 5px;
  justify-items: center;
}

li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }

/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p  { text-align: center; }
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>| true center |</span></p>

Michael Benjamin
fonte
1
Muito bom, obrigado pela explicação! Eu acho que os trechos de código recém-adicionados se beneficiariam de encurtar o texto de exemplo, já que não é realmente evidente na saída que o conteúdo está centralizado / não centralizado devido à pequena viewport. Só eu?
user2651804
"O novo item deve ter a mesma largura que o item D existente, ou as caixas do meio não serão centralizadas com precisão". - que é uma porcaria que deve ser a mesma largura, mas graças a Deus por grade CSS :)
Vucko
Usando a técnica Grid, os itens não estão no ponto morto, existe uma maneira de obter o elemento do logotipo morto no centro? imgur.com/a/SVg9xsj
J86
Não é familiarizado o suficiente com a solução de grade, embora ela funcione como um encanto e seja a mais limpa. Uma pergunta que tenho é como dar mais espaço à coluna do meio que não seja igual aos três?
Saba Ahang
5

Maneira mais fácil

.box{
  display:flex;
  justify-content:center;
}
.item1{
   flex:1;
   display: flex;
   justify-content: center;
   transform: translateX(10px);/*D element Width[if needed]*/
}
 <div class="box">
   <div class="item1">
      <div>A</div>
      <div>B</div>
      <div>C</div>
   </div>
   <div class="item2">D</div>
 </div>

Razib Hossain
fonte
2

Se quiser torná-lo alinhado, basta anexar um espaço vazio e dividir os três trechos filhos neles.

Ali Korkmaz
fonte
2
você pode fornecer uma demonstração curta para fazer backup de sua declaração?
klewis 24/01
2

A solução mais simples será justificar o centro de conteúdo para o contêiner pai e fornecer automaticamente a margem esquerda para o primeiro e o último elemento filho.

ul {
  display:flex;
  justify-content:center;
}


.a,.d {
  margin-left:auto;
}
<ul>
  <li class="a">A</li>
  <li>B</li>
  <li>C</li>
  <li class="d">D</li>
</ul>

Suhail AKhtar
fonte
1

Usando a display:gridabordagem, você pode simplesmente colocar todos os ulfilhos na mesma célula e definir justify-self:

ul {
  display: grid;
}

ul > * {
  grid-column-start: 1;
  grid-row-start: 1;
  justify-self:center;
}

ul > *:last-child {
  justify-self: right;
}

/* Make Fancy */
li {
  display:inline-block;
  margin: 1px;
  padding: 5px;
  background: #bbb;
}
<ul>
  <span>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  </span>
  <li>D</li>
</ul>

Steven Spungin
fonte
0

Pergunta muito clara. Não pude deixar de postar a resposta depois de algumas horas de escavação. Nós poderíamos resolver isso com tabelas, célula de tabela, posições absolutas, transformações, mas só precisávamos fazer isso com o flexbox :)

.parent {
  display: flex;
  justify-content: flex-end;
}

.center {
  margin: auto;
}

http://codepen.io/rgfx/pen/BLorgd

rgfx
fonte
8
Isso realmente não centraliza os itens do meio, porque apenas leva em consideração o espaço restante , não o espaço inteiro . codepen.io/anon/pen/QKGrRk
Michael Benjamin
@ Michael_B, seu direito não percebeu isso, meu mal. Voltar a usar posições absolutas :( Talvez com seu representante alto você deva definir uma recompensa para resolver isso definitivamente. Gostaria, mas tenho um representante muito baixo, ainda mais baixo agora tentando ajudá-lo.
rgfx
Nenhuma recompensa adicionará um novo comportamento ao modelo do flexbox, o, por Michael_B, a resposta dada é a melhor possível ... hoje.
Ason
0

I expandiu Michael_B 's resposta

.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3) {
  flex: 1;
}
.center-flex__2-of-3 > :nth-child(1) {
  justify-content: flex-start;
}
.center-flex__2-of-3 > :nth-child(3) {
  justify-content: flex-end;
}
.center-flex__1-of-2 > :nth-child(1) {
  margin: auto;
}
.center-flex__1-of-2 > :nth-child(2) {
  flex: 1;
  justify-content: flex-end;
}
.center-flex__2-of-2 > :nth-child(1) {
  flex: 1;
  justify-content: flex-start;
}
.center-flex__2-of-2 > :nth-child(2) {
  margin: auto;
}
.center-flex__1-of-2:before, .center-flex__1-of-1:before {
  content: '';
  flex: 1;
}
.center-flex__1-of-1:after, .center-flex__2-of-2:after {
  content: '';
  flex: 1;
}

[class*=center-flex] {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  border: 10px solid rgba(0, 0, 0, 0.1);
}
[class*=center-flex] > * {
  display: flex;
}
li {
  padding: 3px 5px;
}
2 of 3
<ul class="center-flex__2-of-3">
  <span>
    <li>Accusamus</li>
    <li>Porro</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

<br><br>
1 of 1
<ul class="center-flex__1-of-1">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

Aqui com a ajuda do SASS como codepen

yunzen
fonte
0

Inspirado no Método # 5: Layout de grade CSS da solução de @Michal Benjamin e porque estou usando Tailwind e, a partir de agora, ainda não tenho acesso a todas as opções de grade por padrão. Isso parece funcionar:

ul {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
li:nth-child(1) { justify-content: flex-start; } // OR: margin-right: auto
li:nth-child(3) { justify-content: flex-end; } // OR: margin-left:auto
li: {align-self: center;}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>

PS: Não tenho certeza se misturar flex e grid dessa maneira é uma boa ideia!

Saba Ahang
fonte
1
você não está misturando grade e flex, justifty-content é uma propriedade de grade CSS E propriedade flexbox (o mesmo para alinhar-se)
Temani Afif
-1

A resposta aceita pode ser um pouco alterada porque você pode usar áreas de modelo de grade e fazê-lo sem elemento falso

grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr
repo
fonte
-1
ul { 
  padding: 0; 
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  position:absolute;
  right:10px;

}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
SUDHIR KUMAR
fonte