Alinhar um elemento ao fundo com o flexbox

375

Eu tenho um divcom algumas crianças:

<div class="content">
  <h1>heading 1</h1>
  <h2>heading 2</h2>
  <p>Some more or less text</p>
  <a href="/" class="button">Click me</a>
</div>

e eu quero o seguinte layout:

 -------------------
|heading 1          |
|heading 2          | 
|paragraph text     |
|can have many      |
|rows               |
|                   |
|                   |
|                   | 
|link-button        |
 -------------------

Independentemente da quantidade de texto em que peu quero manter o .buttonsempre na parte inferior sem tirá-lo do fluxo. Ouvi dizer que isso pode ser possível com o Flexbox, mas não consigo fazê-lo funcionar.

supersize
fonte
7
Apenas dê isso postition: absolute; bottom 0;?
Jonathan
12
@ Jonathan, o invólucro não tem uma altura fixa. Se eu retirá-lo do fluxo, ele sobrepõe o texto
supersize
2
@ Supersize Q antigo, mas você poderia ter dado o wrapper position:relative- é ridículo porque acho que é relativo por padrão, mas você o definiu para que o posicionamento absoluto da criança seja contido. Então bottom:0vai caber nivelado.
Jacksonkr
Jacksonkr é certo, esta é a melhor solução, outros são muito longo, muito complicado ou não está funcionando da maneira certa
Barbz_YHOOL
2
@Jacksonkr a posição padrão de uma div staticnão é relative.
supersize

Respostas:

641

Você pode usar margens automáticas

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

Então você pode usar um destes (ou ambos):

p { margin-bottom: auto; } /* Push following elements to the bottom */
a { margin-top: auto; } /* Push it and following elements to the bottom */

Como alternativa, você pode fazer o elemento antes do acrescimento para preencher o espaço disponível:

p { flex-grow: 1; } /* Grow to fill available space */

Oriol
fonte
2
Para mim, isso funciona no Chrome, mas não no Safari no iOS 10.2. Alguém pode confirmar?
30516 Matthew
@Oriol Eu gosto dessa abordagem, mas não o efeito colateral de perder margens em colapso, o que você faria sobre isso?
Neil
11
flex-grow funcionou para mim. Como faço para fazer isso?html { height: 100%; } body { min-height: 100%; display: flex; flex-direction: column; } #site-content { flex: 1; }
protoEvangelion
2
Também uma nota de lado, lembre-se height: 100%sobre o elemento pai do que você está tentando empurrar algo para baixo commargin-top: auto;
skolind
11
"qualquer espaço livre positivo é distribuído para margens automáticas nessa dimensão." são pequenas coisas assim que são tão elegantes, para mim essa solução foi de 2 linhas de código com base na sua resposta. obrigado :)
danjah
146

Você pode usar display: flex para posicionar um elemento na parte inferior, mas não acho que você queira usar flex nesse caso, pois isso afetará todos os seus elementos.

Para posicionar um elemento na parte inferior usando flex, tente o seguinte:

.container {
  display: flex;
}

.button {
  align-self: flex-end;
}

Sua melhor aposta é definir position: absoluto para o botão e configurá-lo para bottom: 0, ou você pode colocar o botão fora do contêiner e usar negativo transform: translateY(-100%)para trazê-lo para o contêiner da seguinte maneira:

.content {
    height: 400px;
    background: #000;
    color: #fff;
}
.button {
    transform: translateY(-100%);
    display: inline-block;
}

Verifique este JSFiddle

Roumelis George
fonte
6
se você quiser na parte inferior, defina a direção da flexão como coluna.
Viliami
3
E se eu não puder fornecer a altura?
Mark
O que funcionou para mim foi apenas: ``. conteúdo {display: flex; direção flexível: coluna; justificar conteúdo: flex-end; } <div class = "content"> <a class="bottom"> Algo </a> </div> `` `
gsalgadotoledo 16/01/19
84

A solução com align-self: flex-end;não funcionou para mim, mas esta funcionou caso você queira usar o flex:

Resultado

 -------------------
|heading 1          |
|heading 2          | 
|paragraph text     |
|                   |
|                   |
|                   | 
|link button        |
 -------------------

Código

Nota: Ao "executar o snippet de código", é necessário rolar para baixo para ver o link na parte inferior.

.content {
  display: flex;
  justify-content: space-between;
  flex-direction: column;
  height: 300px;
}

.content .upper {
  justify-content: normal;
}

/* Just to show container boundaries */
.content .upper, .content .bottom, .content .upper > * {
  border: 1px solid #ccc;
}
<div class="content">
  <div class="upper">
	  <h1>heading 1</h1>
	  <h2>heading 2</h2>
	  <p>paragraph text</p>
  </div>

  <div class="bottom">
	  <a href="/" class="button">link button</a>
  </div>
</div>

Timo
fonte
11
content é o contêiner da coluna que contém outros 2 contêineres, com justify-content: space-between; você diz a flexbox para empurrar o recipiente longe um do outro quanto possível (neste caso limitada pela altura do recipiente de conteúdo)
ConquerorsHaki
Isso não é o resultado real, ela terá espaço entre cada item (daí o nome)
Barbz_YHOOL
11
@Barbz_YHOOL Não, ele funciona se você aumentar a altura do recipiente (ver exemplo atualizado)
Timo
11
Depois de pesquisar muito, isso é perfeito! Obrigado.
Rudy
11
Com um pouco de modificação, esta resposta funcionou perfeitamente para mim, obrigado
RealMJDev
2

Não tem certeza sobre o flexbox, mas você pode fazer isso usando a propriedade position.

definir div position: relative elemento pai e filho que pode ser um <p>ou <h1>etc. definir position: absolutee bottom: 0.

Exemplo:

index.html

<div class="parent">
  <p>Child</p>
</div>

style.css

.parent {
  background: gray;
  width: 10%;
  height: 100px;    
  position: relative;
}
p {
  position: absolute;
  bottom: 0;
}

Código caneta aqui.

Sanjay Shr
fonte
11
position:fixednão funcionaria porque então não seria relativo ao contêiner em que está. Talvez você quis dizer position:absolute?
precisa
11
Embora esse código possa responder à pergunta, fornecer um contexto adicional a respeito de por que e / ou como esse código responde à pergunta melhora seu valor a longo prazo.
Rollstuhlfahrer
11
Resposta atualizada.
Sanjay Shr
1

insira a descrição da imagem aqui

<section style="display:flex; flex-wrap:wrap;">
    <div style="display:flex; flex-direction:column; flex:1;">
        <button style="margin-top: auto;"/>
    </div>
    <div style="display:flex; flex-direction:column; flex:1;">
        <button style="margin-top: auto;"/>
    </div>
</section>

Demonstração: https://codepen.io/ferittuncer/pen/YzygpWX

ferit
fonte
0

Ao definir sua exibição para flex , você pode simplesmente usar a flexpropriedade para marcar qual conteúdo pode crescer e qual não.

Propriedade Flex

div.content {
 height: 300px;
 display: flex;
 flex-direction: column;
}

div.up {
  flex: 1;
}

div.down {
  flex: none;
}
<div class="content">
  <div class="up">
    <h1>heading 1</h1>
    <h2>heading 2</h2>
    <p>Some more or less text</p>
  </div>

  <div class="down">
    <a href="/" class="button">Click me</a>
  </div>
</div>

Tomas Vancoillie
fonte
-1

Tente isto

.content {
      display: flex;
      flex-direction: column;
      height: 250px;
      width: 200px;
      border: solid;
      word-wrap: break-word;
    }

   .content h1 , .content h2 {
     margin-bottom: 0px;
    }

   .content p {
     flex: 1;
    }
   <div class="content">
  <h1>heading 1</h1>
  <h2>heading 2</h2>
  <p>Some more or less text</p>
  <a href="/" class="button">Click me</a>
</div>

mohxn ayaz
fonte
-1

Acabei de encontrar uma solução para isso.

para quem não estiver satisfeito com as respostas fornecidas, tente esta abordagem com o flexbox

CSS

    .myFlexContainer {
        display: flex;
        width: 100%;
    }

    .myFlexChild {
        width: 100%;
        display: flex;

        /* 
         * set this property if this is set to column by other css class 
         *  that is used by your target element 
         */
        flex-direction: row;

        /* 
         * necessary for our goal 
         */
        flex-wrap: wrap;
        height: 500px;
    }

    /* the element you want to put at the bottom */
    .myTargetElement {
        /*
         * will not work unless flex-wrap is set to wrap and 
         * flex-direction is set to row
         */
        align-self: flex-end;
    }

HTML

    <div class="myFlexContainer">
        <div class="myFlexChild">
            <p>this is just sample</p>
            <a class="myTargetElement" href="#">set this to bottom</a>
        </div>
    </div>
aj go
fonte