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.


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.


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.


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ê.


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.


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>


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;
  }
}

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.


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.


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);

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>


0

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

    .my-element {
      position: absolute;
      bottom: 30px;
    }

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/


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


-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


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.