Fazer div posicionado absoluto expandir a altura div do pai

204

Como você pode ver no CSS abaixo, quero child2me posicionar antes child1. Isso ocorre porque o site que estou desenvolvendo no momento também deve funcionar em dispositivos móveis, nos quais child2deve estar na parte inferior, pois contém a navegação desejada abaixo do conteúdo dos dispositivos móveis. - Por que não 2 páginas-mestre? Estes são os únicos 2 divsque são reposicionados em todo o HTML, portanto, 2 páginas-mestre dessa pequena alteração são um exagero.

HTML:

<div id="parent">
    <div class="child1"></div>
    <div class="child2"></div>
</div>

CSS:

parent { position: relative; width: 100%; }
child1 { width: auto; margin-left: 160px; }
child2 { width: 145px; position: absolute; top: 0px; bottom: 0px; }

child2 possui altura dinâmica, pois subsites diferentes podem ter mais ou menos itens de navegação.

Eu sei que elementos posicionados absolutos são removidos do fluxo, sendo ignorados por outros elementos.
Eu tentei definir overflow:hidden;a div pai, mas isso não ajudou, nem o clearfix.

Meu último recurso será o JavaScript para reposicionar os dois de divsacordo, mas, por enquanto, tentarei ver se existe uma maneira não-JavaScript de fazer isso.

Micha Wiedenmann
fonte
3
Não tenho 100% de certeza, mas acho que você provavelmente terá que optar por uma solução JS que calcule a altura de child2 e mova child1 de acordo.
precisa saber é o seguinte
2
Isso pode ser feito definindo a posição dos pais como relativa e a criança como absoluta.
Fungusanthrax #
1
Veja esta solução alternativa, talvez possa ajudar.
precisa saber é o seguinte

Respostas:

153

Você respondeu a pergunta por si mesmo: "Eu sei que elementos posicionados absolutos são removidos do fluxo, sendo ignorados por outros elementos". Portanto, você não pode definir a altura dos pais de acordo com um elemento absolutamente posicionado.

Você usa alturas fixas ou precisa envolver o JS.

feeela
fonte
1
Estou marcando isso como tecnicamente é a maneira correta, embora eu tenha encontrado outra solução para o meu problema, que é praticamente aninhar o css necessário nas páginas específicas que precisam ser diferenciadas (2 de 40 no momento).
16

Embora position: absolutenão seja possível esticar para elementos com , muitas vezes existem soluções nas quais você pode evitar o posicionamento absoluto enquanto obtém o mesmo efeito. Veja este violino que resolve o problema no seu caso específico http://jsfiddle.net/gS9q7/

O truque é reverter a ordem dos elementos flutuando os dois elementos, o primeiro para a direita, o segundo para a esquerda, para que o segundo apareça primeiro.

.child1 {
    width: calc(100% - 160px);
    float: right;
}
.child2 {
    width: 145px;
    float: left;
}

Por fim, adicione uma correção clara aos pais e pronto (veja o violão para a solução completa).

Geralmente, desde que o elemento com posição absoluta esteja posicionado na parte superior do elemento pai, é bem provável que você encontre uma solução alternativa ao flutuar o elemento.

lex82
fonte
10

Feeela está certa, mas você pode obter um paidivcontratando / expandindo para um elemento filho se você reverter seudivposicionamento assim:

.parent{
    postion: absolute;
    /* position it in the browser using the `left`, `top` and `margin` 
       attributes */
}

.child{
    position: relative;
    height: 100%;
    width: 100%;

    overflow: hidden;
    /* to pad or move it around using `left` and `top` inside the parent */
}

Isso deve funcionar para você.

ChrisC
fonte
9

Existe uma maneira bastante simples de resolver isso.

Você apenas precisa duplicar o conteúdo de child1 e child2 em divs relativos com display: none na div pai. Diga filho1_1 e filho2_2. Coloque child2_2 em cima e child1_1 na parte inferior.

Quando seu jquery (ou o que for) chama a div absoluta, basta definir a div relativa correspondente (child1_1 ou child2_2) com display: block AND visibilidade: hidden. O filho relativo ainda estará invisível, mas aumentará a divisão dos pais.

MMB
fonte
2
Isso me fez pensar na direção certa. Na minha exibição de configuração de caso: nenhum no conteúdo "size holder" faz com que a div não seja dimensionada, porém opacidade: 0, dimensiona a div corretamente e não requer nenhum jquery adicional.
Edencorbin
A maneira que fiz foi obter dois divs duplicados, o primeiro é o conteúdo visível com posição absoluta e o segundo é um div com visibilidade oculta, que mantém o div pai com a altura correta, tudo funciona bem = D
Diogo Garcia
4

Com JavaScript puro, você só precisa recuperar a altura do static positionelemento filho .child1usando o método getComputedStyle () e defina esse valor de recuperação como o padding-topmesmo filho usando a propriedade HTMLElement.style .


Verifique e execute o seguinte snippet de código para obter um exemplo prático do que descrevi acima:

/* JavaScript */

var child1 = document.querySelector(".child1");
var parent = document.getElementById("parent");

var childHeight = parseInt(window.getComputedStyle(child1).height) + "px";
child1.style.paddingTop = childHeight;
/* CSS */

#parent { position: relative; width: 100%; }
.child1 { width: auto; }
.child2 { width: 145px; position: absolute; top: 0px; bottom: 0px; }
html, body { width: 100%;height: 100%; margin: 0; padding: 0; }
<!-- HTML -->

<div id="parent">
    <div class="child1">STATIC</div>
    <div class="child2">ABSOLUTE</div>
</div>

AndrewL64
fonte
3

Esta pergunta foi feita em 2012 antes da flexbox. A maneira correta de resolver esse problema usando CSS moderno é com uma consulta de mídia e uma reversão de coluna flexível para dispositivos móveis. Nenhum posicionamento absoluto é necessário.

https://jsfiddle.net/tnhsaesop/vjftq198/3/

HTML:

<div class="parent">
  <div style="background-color:lightgrey;">
    <p>
      I stay on top on desktop and I'm on bottom on mobile
    </p>
  </div>
  <div style="background-color:grey;">
    <p>
      I stay on bottom on desktop and I'm on bottom on mobile
    </p>
  </div>
</div>

CSS:

.parent {
  display: flex;
  flex-direction: column;
}

@media (max-width: 768px) {
  .parent {
    flex-direction: column-reverse;
  }
}
Hunter Nelson
fonte
2

Eu tive um problema parecido. Para resolver isso (em vez de calcular a altura do iframe usando o corpo, documento ou janela), criei uma div que agrupa todo o conteúdo da página (uma div com um id = "página" por exemplo) e depois usei sua altura.

Juliano
fonte
1

Eu vim com outra solução, que eu não amo, mas faz o trabalho.

Duplique basicamente os elementos filhos de maneira que as duplicatas não sejam visíveis.

<div id="parent">
    <div class="width-calc">
        <div class="child1"></div>
        <div class="child2"></div>
    </div>

    <div class="child1"></div>
    <div class="child2"></div>
</div>

CSS:

.width-calc {
    height: 0;
    overflow: hidden;
}

Se esses elementos filhos contiverem pouca marcação, o impacto será pequeno.

btx9000
fonte
4
Isto pode dar alguns problemas com o ranking do motor de busca
mschadegg
1

"Você usa alturas fixas ou precisa envolver o JS."

Aqui está o exemplo JS:

---------- Exemplo jQuery JS --------------------

    function findEnvelopSizeOfAbsolutelyPositionedChildren(containerSelector){
        var maxX = $(containerSelector).width(), maxY = $(containerSelector).height();

        $(containerSelector).children().each(function (i){
            if (maxX < parseInt($(this).css('left')) + $(this).width()){
                maxX = parseInt($(this).css('left')) + $(this).width();
            }
            if (maxY < parseInt($(this).css('top')) + $(this).height()){
                maxY = parseInt($(this).css('top')) + $(this).height();
            }
        });
        return {
            'width': maxX,
            'height': maxY
        }
    }

    var specBodySize = findEnvelopSizeOfAbsolutelyPositionedSubDivs("#SpecBody");
    $("#SpecBody").width(specBodySize.width);
    $("#SpecBody").height(specBodySize.height);
Nikolay
fonte
Esta resposta pode se beneficiar de uma melhor explicação e direção da solução proposta.
DaniDev 28/02
1

Há um hack muito simples que corrige esse problema

Aqui está uma caixa de código que ilustra a solução: https://codesandbox.io/s/00w06z1n5l

HTML

<div id="parent">
  <div class="hack">
   <div class="child">
   </div>
  </div>
</div>

CSS

.parent { position: relative; width: 100%; }
.hack { position: absolute; left:0; right:0; top:0;}
.child { position: absolute; left: 0; right: 0; bottom:0; }

você pode brincar com o posicionamento da div hack para afetar onde a criança se posiciona.

Aqui está um trecho:

html {
  font-family: sans-serif;
  text-align: center;
}

.container {
  border: 2px solid gray;
  height: 400px;
  display: flex;
  flex-direction: column;
}

.stuff-the-middle {
  background: papayawhip
    url("https://camo.githubusercontent.com/6609e7239d46222bbcbd846155351a8ce06eb11f/687474703a2f2f692e696d6775722e636f6d2f4e577a764a6d6d2e706e67");
  flex: 1;
}

.parent {
  background: palevioletred;
  position: relative;
}

.hack {
  position: absolute;
  left: 0;
  top:0;
  right: 0;
}
.child {
  height: 40px;
  background: rgba(0, 0, 0, 0.5);
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
}
    <div class="container">
      <div class="stuff-the-middle">
        I have stuff annoyingly in th emiddle
      </div>
      <div class="parent">
        <div class="hack">
          <div class="child">
            I'm inside of my parent but absolutely on top
          </div>
        </div>
        I'm the parent
        <br /> You can modify my height
        <br /> and my child is always on top
        <br /> absolutely on top
        <br /> try removing this text
      </div>
    </div>

bernatfortet
fonte
0

Existe uma maneira melhor de fazer isso agora. Você pode usar a propriedade bottom.

    .my-element {
      position: absolute;
      bottom: 30px;
    }
rlasch
fonte
5
isso só funcionará se você sabe a altura final do pai, o que você não faz
machineaddict
0

Isso é muito semelhante ao que o @ChrisC sugeriu. Não está usando um elemento posicionado absoluto, mas um elemento relativo. Talvez possa trabalhar para você

<div class="container">
  <div class="my-child"></div>
</div>

E seu css assim:

.container{
    background-color: red;
    position: relative;
    border: 1px solid black;
    width: 100%;
}

.my-child{
    position: relative;
    top: 0;
    left: 100%;
    height: 100px;
    width: 100px;
    margin-left: -100px;
    background-color: blue;
}

https://jsfiddle.net/royriojas/dndjwa6t/

roy riojas
fonte
0

Considere também a próxima abordagem:

CSS:

.parent {
  height: 100%;
}
.parent:after {
  content: '';
  display: block;
}

Além disso, como você está tentando reposicionar divs, considere a grade css

Iegor Benzyk
fonte
-2

As vistas absolutas se posicionam contra o ancestral mais próximo que não está estaticamente posicionado ( position: static); portanto, se você quiser uma vista absoluta posicionada contra um determinado pai, defina o pai positioncomo relativee o filho positioncomoabsolute

Isaac Sekamatte
fonte
-4

Tente isso, foi trabalhado para mim

.child {
    width: 100%;
    position: absolute;
    top: 0px;
    bottom: 0px;
    z-index: 1;
}

Ele definirá a altura do filho como a altura do pai

Sarath E
fonte
ótima solução!
Alexander Cherednichenko
3
@AlexanderCherednichenko Não, na verdade, ela perde o objetivo da pergunta.
precisa saber é o seguinte