Posicionamento absoluto, ignorando o preenchimento do pai

173

Como você faz um elemento posicionado absoluto honrar o preenchimento de seu pai? Eu quero que uma div interna se estenda pela largura do pai e seja posicionada na parte inferior desse pai, basicamente um rodapé. Mas a criança tem que honrar o estofamento dos pais e não está fazendo isso. A criança é pressionada contra a borda dos pais.

Então, eu quero isso:

insira a descrição da imagem aqui

mas estou entendendo isso:

insira a descrição da imagem aqui

<html>
  <body>
    <div style="background-color: blue; padding: 10px; position: relative; height: 100px;">
      <div style="background-color: gray; position: absolute; left: 0px; right: 0px; bottom: 0px;">css sux</div>
    </div>
  </body>
</html>

Posso fazer isso acontecer com uma margem em torno da div interna, mas prefiro não ter que adicionar isso.

d512
fonte
5
Por que não mudar a esquerda / direita / parte inferior da div interna para style="background-color: gray; position: absolute; left: 10px; right: 10px; bottom: 10px;"?
j08691
12
Sim, eu pensei nisso, mas rapidamente se torna uma dor de cabeça de manutenção, porque toda criança precisa ter seu próprio conjunto de compensações para dar conta disso. Se eles apenas honrassem o estofamento dos pais, você poderia colocá-lo apenas uma vez nos pais e não se preocupar com todos os filhos.
D512
Como indicado acima, se você usar o valor do preenchimento dos pais (em relação posicionada) como o left:e right:sobre a criança (absoluto posicionada), o problema está resolvido. Estou adicionando este b / c que é a resposta que outras pessoas com o mesmo problema provavelmente estão procurando.
rda3000
Tem um problema semelhante aqui: jsfiddle.net/5n4By/6 . O rodapé está honrando o preenchimento esquerdo do pai, mas transborda à direita. Você esperaria que ele honrasse o preenchimento correto, assim como se mantivesse consistente ...
rafiki_rafi 12/12/13

Respostas:

186

Primeiro, vamos ver por que isso está acontecendo.

O motivo é que, surpreendentemente, quando uma caixa tem position: absolutesua caixa contendo a caixa de preenchimento dos pais (ou seja, a caixa em torno do preenchimento). Isso é surpreendente, porque geralmente (ou seja, ao usar o posicionamento estático ou relativo) a caixa que contém é a caixa de conteúdo dos pais .

Aqui está a parte relevante da especificação CSS :

No caso de o ancestral ser um elemento embutido, o bloco que contém é a caixa delimitadora em torno das caixas de preenchimento da primeira e da última caixa embutida geradas para esse elemento ... Caso contrário, o bloco que contém é formado pela borda do preenchimento de o ancestral.

A abordagem mais simples - como sugerido na resposta de Winter - é usar padding: inheritno absolutamente posicionado div. Só funciona, no entanto, se você não quiser que o absolutamente posicionado divtenha algum preenchimento adicional próprio. Eu acho que as soluções de uso geral (em que ambos os elementos podem ter seu próprio preenchimento independente) são:

  1. Adicione um extra relativamente posicionado div(sem preenchimento) ao redor do absolutamente posicionado div. Esse novo divrespeitará o preenchimento de seu pai e o absolutamente posicionado divo preencherá.

    A desvantagem, é claro, é que você está mexendo com o HTML simplesmente para fins de apresentação.

  2. Repita o preenchimento (ou adicione a ele) no elemento absolutamente posicionado.

    A desvantagem aqui é que você deve repetir os valores no seu CSS, que é quebradiço se você estiver escrevendo o CSS diretamente. No entanto, se você estiver usando uma ferramenta de pré-processamento como SASSou LESSpode evitar esse problema usando uma variável. Esse é o método que eu pessoalmente uso.

Kevin Christopher Henry
fonte
Por que esse é o padrão position: absolute? É surpreendente que a caixa que contém é a caixa de preenchimento, mas deve ter havido uma razão para isso, assim como tenho certeza de que há uma razão pela qual (sem box-sizing) o width& heightnão inclui o preenchimento ou a borda.
trysis
1
Apenas uma adição: nada disso é afetado pela box-sizingpropriedade, no pai ou no filho. Isso ocorre porque isso afeta o dimensionamento , como na largura / altura, mas não na caixa que contém, embora eu admita que faria mais sentido se afetasse os dois.
trysis
2
Esta é uma boa informação, mas é a resposta ERRADA. A resposta certa é a de inverno abaixo ... use padding: herdar e seu elemento Absolute obterá o preenchimento necessário. Não sei por que isso tem mais
votos positivos do
1
@NotaGuruAtAll: padding: inheritfunciona bem se o absolutamente posicionado divnão precisar de preenchimento próprio, e eu adicionei uma menção a essa técnica. É menos flexível, porém, porque você não pode adicionar nenhum preenchimento adicional ao absolutamente posicionado div(ou seja, você não pode dizer padding: inherit + 5px). Por isso prefiro as técnicas mencionadas aqui.
Kevin Christopher Henry
1
O preenchimento herdado no position:absoluteelemento filho realmente funciona se você estiver apenas procurando que a criança respeite o preenchimento dos pais. No entanto, se você deseja adicionar preenchimento adicional à criança, você deve manter a proporção de preenchimentos em seu código. Não há maneira limpa de fazer isso apenas com CSS.
Dylan Pierce
51

Uma coisa que você pode tentar é usar o seguinte css:

.child-element {
    padding-left: inherit;
    padding-right: inherit;
    position: absolute;
    left: 0;
    right: 0;
}

Ele permite que o elemento filho herde o preenchimento do pai, e o filho pode ser posicionado para corresponder ao tamanho e ao preenchimento dos pais.

Além disso, estou usando box-sizing: border-box;os elementos envolvidos.

Não testei isso em todos os navegadores, mas parece estar funcionando no Chrome, Firefox e IE10.

Inverno
fonte
Combinei esta resposta e a resposta do @NewSpender. No meu caso particular, a div posicionada absoluta continuou ignorando o preenchimento, mas foi delimitada por seu elemento pai. Então, dar o div posicionado absoluto com bordas grossas brancas imitou o preenchimento que eu precisava. Um pré-requisito, porém, é que seu plano de fundo precise ter a mesma cor.
Ogier Schelvis
Mas o OP não quer que o filho herde o preenchimento dos pais. Ele quer que a criança seja compensada de acordo com o preenchimento dos pais.
Michael Gummelt
30

Bem, essa pode não ser a solução mais elegante (semanticamente), mas em alguns casos funcionará sem inconvenientes: em vez de preenchimento, use uma borda transparente no elemento pai. Os elementos filhos posicionados absolutos respeitarão a borda e ela será renderizada exatamente da mesma forma (exceto se você estiver usando a borda do elemento pai para estilizar).

NewSpender
fonte
6

Aqui está minha melhor chance. Eu adicionei outra Div e a deixei vermelha e alterei a altura dos seus pais para 200px apenas para testá-la. A idéia é que o filho agora se torna neto e os pais se tornam avós. Portanto, o pai respeita o pai. Espero que você entenda minha ideia.

<html>
  <body>
    <div style="background-color: blue; padding: 10px; position: relative; height: 200px;">
     <div style="background-color: red;  position: relative; height: 100%;">    
        <div style="background-color: gray; position: absolute; left: 0px; right: 0px;bottom: 0px;">css sux</div>
     </div>
    </div>
  </body>
</html>

Editar:

Eu acho que o que você está tentando fazer não pode ser feito. Posição absoluta significa que você dará coordenadas que deve honrar. E se o pai tiver um preenchimento de 5px. E você absolutamente posiciona a criança no topo: -5px; esquerda: -5px . Como é supor honrar os pais e você ao mesmo tempo?

Minha solução

Se você quer homenagear os pais, não o posicione absolutamente.

Tocar
fonte
Obrigado, agradeço a publicação, mas ainda é uma solução alternativa para o problema real. O que realmente quero saber é se você pode fazer as crianças honrarem o preenchimento do elemento pai. Se a resposta for não, eu darei o representante.
D512
Se você os posicionar absolutamente, eles não honrarão o elemento pai. Eles vão te honrar. Pelo mesmo motivo, se você não os posicionar absolutamente, não poderá usar coisas como bottom: 10px porque elas respeitam o elemento pai. Mas o que você quer fazer, suponho, abrirá espaço para uma contradição e, portanto, será diferente nos navegadores. Eu acho que apenas uma solução alternativa funcionará.
Toque
3
O posicionamento absoluto honra o pai, esse é o sistema de coordenadas que ele usa. Quando você diz 0px superior, significa 0px da parte superior do pai. A questão é se deve ou não levar em consideração os pais. Se o pai tivesse um preenchimento de 5px e você desse ao filho: -5px, ele o colocaria nivelado com o pai se o preenchimento do pai fosse respeitado ou 5px acima do pai, se não fosse.
D512
3

1.) você não pode usar borda grande no pai - caso deseje ter uma borda específica

2.) você não pode adicionar margem - caso seu pai faça parte de algum outro contêiner e deseje que seu pai aproveite ao máximo largura desse grande pai.

A única solução que deve ser aplicável é embrulhar seus filhos em outro recipiente para que seus pais se tornem avós e, em seguida, aplique estofamento no novo invólucro / pai das crianças. Ou você pode aplicar diretamente estofamento às crianças.

No seu caso:

.css-sux{
  padding: 0px 10px 10px 10px;
}
bhavya_w
fonte
1

Poderia ter feito facilmente usando um nível extra de Div.

<div style="background-color: blue; padding: 10px; position: relative; height: 100px;">
  <div style="position: absolute; left: 0px; right: 0px; bottom: 10px; padding:0px 10px;">
    <div style="background-color: gray;">css sux</div>
  </div>
</div>

Demonstração: https://jsfiddle.net/soxv3vr0/

asankasri
fonte
0

adicionar preenchimento: herdar em sua posição absoluta

.box{
  background: red;
  position: relative;
  padding: 30px;
  width:500px;
  height:200px;
 box-sizing: border-box;
 

}
<div  class="box">

  <div style="position: absolute;left:0;top:0;padding: inherit">top left</div>
  <div style="position: absolute;right:0;top:0;padding: inherit">top right</div>
  <div style="text-align: center;padding: inherit">center</div>
  <div style="position: absolute;left:0;bottom:0;padding: inherit">bottom left</div>
  <div style="position: absolute;right:0;bottom:0;padding: inherit">bottom right</div>


</div>

ßãlãjî
fonte