CSS 100% de altura com preenchimento / margem

813

Com HTML / CSS, como criar um elemento com largura e / ou altura que seja 100% do elemento pai e ainda ter margens ou preenchimento adequados?

Por "apropriado", quero dizer que, se meu elemento pai for 200pxalto e eu especificar height = 100%com, padding = 5pxeu esperaria que eu recebesse um 190pxelemento alto border = 5pxde todos os lados, bem centralizado no elemento pai.

Agora, eu sei que não é assim que o modelo de caixa padrão especifica que ele funcione (embora eu queira saber exatamente o porquê ...), portanto a resposta óbvia não funciona:

#myDiv {
    width: 100%
    height: 100%;
    padding: 5px;
}

Mas parece-me que deve haver ALGUM modo de produzir esse efeito de maneira confiável para um pai de tamanho arbitrário. Alguém sabe como realizar essa tarefa (aparentemente simples)?

Ah, e para constar, não estou muito interessado na compatibilidade com o IE, de modo que (espero) torne as coisas um pouco mais fáceis.

EDIT: Como um exemplo foi solicitado, aqui está o mais simples que consigo pensar:

<html style="height: 100%">
    <body style="height: 100%">
        <div style="background-color: black; height: 100%; padding: 25px"></div>
    </body>
</html>

O desafio é fazer com que a caixa preta apareça com um preenchimento de 25 pixels em todas as bordas, sem que a página fique grande o suficiente para exigir barras de rolagem.

Toji
fonte
Eu achei essas duas soluções as mais confiáveis: http://www.xs4all.nl/~peterned/examples/csslayout1.html http://themaninblue.com/experiment/footerStickAlt/ Você tem algum HTML específico que podemos ver e brincar?
27612 Nick Presta

Respostas:

755

Eu aprendi como fazer esse tipo de coisa lendo " PRO HTML e CSS Design Patterns ". O display:blocké o valor de exibição padrão para o div, mas eu gosto de torná-lo explícito. O contêiner deve ser do tipo certo; positionatributo é fixed, relative, ou absolute.

.stretchedToMargin {
  display: block;
  position:absolute;
  height:auto;
  bottom:0;
  top:0;
  left:0;
  right:0;
  margin-top:20px;
  margin-bottom:20px;
  margin-right:80px;
  margin-left:80px;
  background-color: green;
}
<div class="stretchedToMargin">
  Hello, world
</div>

Fiddle pelo comentário de Nooshu

Frank Schwieterman
fonte
42
Excelente solução, será marcar este. Adicionei-o rapidamente ao jsfiddle.net/Rpdr9 para quem quiser uma demonstração ao vivo. Espero que você não se importe.
Nooshu 04/03/10
16
Embora o @Toji não se preocupasse com a compatibilidade do IE, infelizmente tenho que fazê-lo. Esta solução não funcionou inicialmente no IE6. A adição do IE9.js de Dean Edwards à página fez esse trabalho. Agora eu só tenho que esperar e rezar para que o posicionamento relativo / absoluto não parafuso com algo em um elemento filho ...
Christopher Parker
24
-1 (embora pareça que sou uma minoria aqui: P). Isso pressupõe que a caixa possa estar absolutamente posicionada; as pessoas já usam demais o pos: abs, pois não precisam dessa munição. Veja este exemplo: uma div "panel" com várias divs da classe "panel" dentro dela. "painéis" tem {overflow: hidden; height: 300px;} e "panel" têm conteúdo / altura-conteúdo variados, com {border: # 000 1px sólido; flutuar: esquerda; margem direita: 10 px;}. Faça com que todos os "painéis" tenham a altura dos "painéis" sem perder as bordas a qualquer momento. As divs "panel" não podem ser pos: abs'd aqui. A solução do @ Marco funciona para esse cenário, no entanto.
eternicode 03/06
8
Uau, entendi. O top:0, bottom:0essencialmente "esticar" o elemento. Eu só posso fazê-lo funcionar com position:absoluteembora
Matt
7
Você não poderia simplesmente fazer em top:20px;bottom:20px;left:20px;right:20px;vez de usar margens?
#
391

Há uma nova propriedade no CSS3 que você pode usar para alterar a maneira como o modelo de caixa calcula largura / altura, chamado de dimensionamento de caixa.

Ao definir essa propriedade com o valor "border-box", faz com que o elemento aplicado não seja esticado ao adicionar um preenchimento ou borda. Se você definir algo com largura de 100 px e preenchimento de 10 px, ele ainda terá 100 px de largura.

box-sizing: border-box;

Veja aqui para suporte ao navegador . Ele não funciona no IE7 e inferior, no entanto, acredito que o IE7.js de Dean Edward adiciona suporte a ele. Desfrutar :)

Marco Jardim
fonte
45
Finalmente! Estou esperando por esse recurso exato há cerca de 10 anos. Pena que o IE7 não o suporte, mas sempre acho que as pessoas que ainda estão usando o IE não merecem um layout bonito.
cronoklee
2
Isso funcionou no navegador padrão do iPhone / Safari e Android para mim, enquanto a solução absolutamente posicionada acima não funcionou.
Spud
18
Isso é basicamente o mesmo que o modelo de caixa de modo peculiar do IE . Acho que é engraçado como todo mundo odeia no IE mas agora border-boxé de todos herói :)
Matt Greer
14
Para sua informação, o prefixo do navegador para dimensionamento de caixa agora é descartado para todos, menos -moz. Veja paulirish.com/2012/box-sizing-border-box-ftw e os comentários para uma boa discussão
aponzani
3
Sim! Esta é a resposta certa! Agora, 100% de altura dimensiona as coisas corretamente em relação aos pais, sem transbordar. Daria um milhão de +1 se eu pudesse.
Andrew Mao
65

A solução é NÃO usar altura e largura! Anexe a caixa interna usando as partes superior, esquerda, direita, inferior e adicione margem.

.box {margin:8px; position:absolute; top:0; left:0; right:0; bottom:0}
<div class="box" style="background:black">
  <div class="box" style="background:green">
    <div class="box" style="background:lightblue">
      This will show three nested boxes. Try resizing browser to see they remain nested properly.
    </div>
  </div>
</div>

amolk
fonte
6
Up-voto porque você está tecnicamente correto, mas também é basicamente a mesma resposta que Frank (que eu acho que é um pouco mais amigável para os navegadores sloppier lá fora.)
Toji
39

A melhor maneira é com a propriedade calc (). Portanto, seu caso seria semelhante a:

#myDiv {
    width: calc(100% - 5px);
    height: calc(100% - 5px);
    padding: 5px;
}

Simples, limpo, sem soluções alternativas. Apenas certifique-se de não esquecer o espaço entre os valores e o operador (por exemplo, (100%-5px)isso interromperá a sintaxe. Aproveite!

Brian Aderer
fonte
6
Ótima solução. Apenas lembre-se de verificar o suporte ao navegador: Posso usar calc ()
Brett postin
5
Isso não daria 100% de largura e altura a cada preenchimento PLUS de 5px, pois o preenchimento tornaria o elemento 10px mais amplo e maior, respectivamente?
Finalmente, uma boa solução, e não como o resto deles, você coloca o topo, a direita, a base e a esquerda como 0, que funcionará apenas com a posição: absoluta;
Gil Epshtain
Eu acho que o correto é: #myDiv {width: calc (100% - 10px); altura: calc (100% - 10px); estofamento: 5px; } 5 da esquerda e 5 da direita = 10, 5 da parte superior e 5 da parte inferior = 10
Chris P
21

De acordo com a altura da especificação w3c, refere-se à altura da área visível, por exemplo, em um monitor com resolução de 1280x1024 pixels, 100% de altura = 1024 pixels.

min-height refere-se à altura total da página, incluindo o conteúdo, portanto, em uma página em que o conteúdo seja maior que 1024px min-height: 100% se estenderá para incluir todo o conteúdo.

O outro problema é que o preenchimento e a borda são adicionados à altura e largura na maioria dos navegadores modernos, exceto ie6 (ie6 é realmente bastante lógico, mas não está em conformidade com as especificações). Isso é chamado de modelo de caixa. Então, se você especificar

min-height: 100%;
padding: 5px; 

Ele fornecerá 100% + 5px + 5px para a altura. Para contornar isso, você precisa de um contêiner de embalagem.

<style>
    .FullHeight { 
       height: auto !important; /* ie 6 will ignore this */
       height: 100%;            /* ie 6 will use this instead of min-height */
       min-height: 100%;        /* ie 6 will ignore this */
    }

    .Padded {
       padding: 5px;
    }
</style>

<div class="FullHeight">
   <div class="Padded">
      Hello i am padded.
   </div
</div>
Alex
fonte
4
@ Alex: Mas o que torna a div interna (a Padded) 100% da altura da div externa. Minha experiência foi que você acabou de obter um pequeno div dentro de um div maior em altura total.
Lawrence Dol
8

1. Altura total com padding

body {
  margin: 0;
}
.container {
  min-height: 100vh;
  padding: 50px;
  box-sizing: border-box;
  background: silver;
}
<div class="container">Hello world.</div>

2. Altura total com margin

body {
  margin: 0;
}
.container {
  min-height: calc(100vh - 100px);
  margin: 50px;
  background: silver;
}
<div class="container">Hello world.</div>

3. Altura total com border

body {
  margin: 0;
}
.container {
  min-height: 100vh;
  border: 50px solid pink;
  box-sizing: border-box;
  background: silver;
}
<div class="container">Hello world.</div>

Adesivos
fonte
7

Essa é uma das idiotices definitivas do CSS - ainda não entendi o raciocínio (se alguém souber, por favor, explique).

100% significa 100% da altura do contêiner - à qual são adicionadas margens, bordas e preenchimentos. Portanto, é efetivamente impossível obter um contêiner que preencha seu pai e que tenha uma margem, borda ou preenchimento.

Observe também que definir altura também é notoriamente inconsistente entre os navegadores.


Outra coisa que aprendi desde que postei isso é que a porcentagem é relativa ao comprimento do contêiner , ou seja, sua largura, tornando uma porcentagem ainda mais inútil para a altura.

Atualmente, as unidades de janela de visualização vh e vw são mais úteis, mas ainda não são especialmente úteis para outras coisas que não os contêineres de nível superior.

Lawrence Dol
fonte
Não há raciocínio, apenas o que aconteceu quando os navegadores começaram a convergir para um comportamento consistente. Confira o livro mencionado na minha resposta.
Frank Schwieterman
Promovido por usar o termo certo. Tex e qualquer gerente de layout que eu vi acertou, apenas CSS deve ser especial.
Maaartinus
5

Outra solução é usar display: table que possui um comportamento de modelo de caixa diferente.

Você pode definir uma altura e largura para o pai e adicionar preenchimento sem expandi-lo. A criança tem 100% de altura e largura, menos os forros.

JSBIN

Outra opção seria usar propriedades de tamanho de caixa. O único problema com ambos seria que eles não funcionam no IE7.

user1721135
fonte
4

Outra solução: você pode usar unidades de porcentagem para margens e tamanhos. Por exemplo:

.fullWidthPlusMargin {
    width: 98%;
    margin: 1%;
}

O principal problema aqui é que as margens aumentarão / diminuirão ligeiramente com o tamanho do elemento pai. Presumivelmente, a funcionalidade que você prefere é que as margens permaneçam constantes e o elemento filho aumente / diminua para preencher as alterações no espaçamento. Portanto, dependendo do quão apertado você precisa que sua tela seja, isso pode ser problemático. (Eu também optaria por uma margem menor, como 0,3%).

ktbiz
fonte
3

Uma solução com flexbox (trabalhando no IE11): ( ou visualize no jsfiddle )

<html>
  <style>
    html, body {
      height: 100%; /* fix for IE11, not needed for chrome/ff */
      margin: 0; /* CSS-reset for chrome */
    }
  </style>
  <body style="display: flex;">
    <div style="background-color: black; flex: 1; margin: 25px;"></div>
  </body>
</html>

(A redefinição de CSS não é necessariamente importante para o problema real.)

A parte importante é flex: 1(em combinação com display: flexo pai). Curiosamente, a explicação mais plausível que conheço para o funcionamento da propriedade Flex vem de uma documentação nativa de reação, por isso me refiro a ela de qualquer maneira :

(...) flex: 1, que instrui um componente a preencher todo o espaço disponível, compartilhado igualmente entre outros componentes com o mesmo pai

Putzi San
fonte
2

O exemplo de Frank me confundiu um pouco - não funcionou no meu caso porque eu ainda não entendia o posicionamento o suficiente. É importante observar que o elemento do contêiner pai precisa ter uma posição não estática (ele mencionou isso, mas eu o ignorei, e não estava no exemplo dele).

Aqui está um exemplo em que o filho - preenchimento e borda - usa posicionamento absoluto para preencher 100% dos pais. O pai usa o posicionamento relativo para fornecer um ponto de referência para a posição da criança enquanto permanece no fluxo normal - o próximo elemento "mais conteúdo" não é afetado:

#box {
    position: relative;
    height: 300px;
    width: 600px;
}

#box p {
    position: absolute;
    border-style: dashed;
    padding: 1em;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}
<div id="box">
  <p>100% height and width!</p>
</div>
<div id="more-content">
</div>

Um link útil para aprender rapidamente o posicionamento CSS

Peter Tseng
fonte
0

Borda em torno da div, em vez da margem do corpo da página

Outra solução - eu só queria uma borda simples em torno da borda da minha página e queria 100% de altura quando o conteúdo fosse menor que isso.

A caixa de borda não funcionou e o posicionamento fixo parecia errado para uma necessidade tão simples.

Acabei adicionando uma borda ao meu contêiner, em vez de depender da margem do corpo da página - fica assim:

body, html {
    height: 100%;
    margin: 0;
}

.container {
    width: 100%;
    min-height: 100%;
    border: 8px solid #564333;
}
Kris Randall
fonte
0

Esse é o comportamento padrão de display: blockA maneira mais rápida de corrigi-lo em 2020 é definir o display: 'flex'elemento pai e o preenchimento, por exemplo, 20 px, todos os filhos terão 100% de altura em relação à sua altura.

Freestyle09
fonte
0

Adicionar -webkit e -moz seria mais apropriado

-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
user3113626
fonte
-2
  <style type="text/css">
.stretchedToMargin {
    position:absolute;
    width:100%;
    height:100%;

}
</style>
Mujassir Nasir
fonte