CSS 100% de altura con relleno / margen

813

Con HTML / CSS, ¿cómo puedo hacer un elemento que tenga un ancho y / o alto que sea el 100% de su elemento padre y que todavía tenga los márgenes o el relleno adecuado?

Por "apropiado" quiero decir que si mi elemento padre es 200pxalto y especifico height = 100%conpadding = 5px , esperaría que obtuviera un 190pxelemento alto con border = 5pxtodos los lados, bien centrado en el elemento padre.

Ahora, sé que no es así como el modelo de caja estándar especifica que debería funcionar (aunque me gustaría saber por qué, exactamente ...), por lo que la respuesta obvia no funciona:

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

Pero me parece que debe haber ALGUNA forma de producir de manera confiable este efecto para un padre de tamaño arbitrario. ¿Alguien sabe de una manera de lograr esta tarea (aparentemente simple)?

Ah, y para que conste, no estoy terriblemente interesado en la compatibilidad con IE, por lo que (con suerte) debería facilitar las cosas un poco.

EDITAR: dado que se solicitó un ejemplo, aquí está el más simple que se me ocurre:

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

El desafío es entonces que aparezca el cuadro negro con un relleno de 25 píxeles en todos los bordes sin que la página crezca lo suficiente como para requerir barras de desplazamiento.

Toji
fuente
He encontrado que estas dos soluciones son las más confiables: http://www.xs4all.nl/~peterned/examples/csslayout1.html http://themaninblue.com/experiment/footerStickAlt/ ¿Tiene algún HTML específico que podemos ver y jugar?
Nick Presta

Respuestas:

755

Aprendí a hacer este tipo de cosas leyendo " Patrones de diseño PRO HTML y CSS ". El display:blockes el valor de visualización predeterminado para el div, pero me gusta hacerlo explícito. El contenedor debe ser del tipo correcto; positionatributo es fixed, relativeo 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>

El violín por el comentario de Nooshu

Frank Schwieterman
fuente
42
Excelente solución, marcaré este. Simplemente lo agregué rápidamente a jsfiddle.net/Rpdr9 para cualquiera que quiera una demostración en vivo. Espero que no te importe.
Nooshu
16
Si bien a @Toji no le importaba la compatibilidad con IE, desafortunadamente tengo que hacerlo. Esta solución no funcionó inicialmente con IE6. Agregar Dean Edwards ' IE9.js a la página hizo que esto funcionara. Ahora sólo tengo que esperar y rezar para que el posicionamiento relativo / absoluto no tornillo con algo en un elemento hijo ...
Christopher Parker
24
-1 (aunque parece que soy una minoría aquí: P). Esto supone que la caja se puede posicionar absolutamente; las personas ya usan en exceso pos: abs como es, no necesitan esta munición. Tome este ejemplo: un div "paneles" con múltiples divs de clase "panel" dentro de él. "paneles" tiene {desbordamiento: oculto; height: 300px;}, y "panel" tienen diferentes contenidos / content-height, con {border: # 000 solid 1px; flotador izquierdo; margen derecho: 10px;}. Haga que todos los "paneles" tengan la altura de los "paneles" sin perder bordes en ningún punto. El "panel" divs no puede ser pos: abs'd aquí. Sin embargo, la solución de @ Marco funciona para este escenario.
eternicode
8
Oh wow, lo entiendo. El top:0, bottom:0esencialmente "estira" el elemento. Sólo puedo conseguir que funcione con position:absolutepesar
Matt
77
¿No podrías simplemente hacer en top:20px;bottom:20px;left:20px;right:20px;lugar de usar márgenes?
chowey
391

Hay una nueva propiedad en CSS3 que puede usar para cambiar la forma en que el modelo de caja calcula el ancho / alto, se llama dimensionamiento de caja.

Al establecer esta propiedad con el valor "border-box", el elemento que aplique no se estirará al agregar un relleno o borde. Si define algo con un ancho de 100 píxeles y un relleno de 10 píxeles, seguirá siendo de 100 píxeles de ancho.

box-sizing: border-box;

Ver aquí para soporte del navegador . No funciona para IE7 y versiones anteriores , sin embargo, creo que el IE7.js de Dean Edward agrega soporte para ello. Disfruta :)

Marco Jardim
fuente
45
¡Finalmente! Llevo unos 10 años esperando esta característica exacta. Pity IE7 no lo admite, pero siempre pienso que las personas que todavía usan IE no merecen un diseño hermoso.
cronoklee el
2
Esto funcionó en iPhone / Safari y el navegador predeterminado de Android para mí, mientras que la solución posicionada anteriormente no funcionó.
Spud
18
Esto es básicamente lo mismo que el modelo de caja de modo peculiaridades de IE . Me parece curioso cómo todo el mundo odia en IE, pero ahora border-boxes el héroe de todos :)
Matt Greer
14
Para su información, el prefijo del navegador para el tamaño de la caja ahora se elimina para todos menos -moz. Ver paulirish.com/2012/box-sizing-border-box-ftw y los comentarios para una buena discusión
aponzani
3
¡Si! ¡Esta es la respuesta correcta! La altura del 100% ahora escala las cosas correctamente en relación con sus padres, sin extenderse. Daría un millón de +1 si pudiera.
Andrew Mao
65

¡La solución es NO usar la altura y el ancho en absoluto! Adjunte la caja interna usando arriba, izquierda, derecha, abajo y luego agregue margen.

.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
fuente
66
Vota a favor porque eres técnicamente correcto, pero también es básicamente la misma respuesta que la de Frank (que creo que es un poco más amigable para los navegadores más descuidados).
Toji
39

La mejor manera es con la propiedad calc (). Entonces su caso se vería así:

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

Simple, limpio, sin soluciones. Solo asegúrese de no olvidar el espacio entre los valores y el operador (por ejemplo, (100%-5px)eso romperá la sintaxis. ¡Disfrute!

Brian Aderer
fuente
66
Buena solución Solo recuerde verificar el soporte del navegador: ¿Puedo usar calc ()?
Brett Postin
55
¿No le daría esto 100% de ancho y alto a cada relleno PLUS de 5px, ya que el relleno efectivamente haría que el elemento 10px sea más ancho y más grande, respectivamente?
Finalmente, una buena solución, y no como el resto de ellos, coloca la parte superior, derecha, inferior e izquierda para que sea 0, que funcionará solo con position: absolute;
Gil Epshtain
Creo que lo correcto es: #myDiv {ancho: calc (100% - 10px); altura: calc (100% - 10px); acolchado: 5px; } 5 desde la izquierda y 5 desde la derecha = 10, 5 desde arriba y 5 desde abajo = 10
Chris P
21

Según la especificación w3c, la altura se refiere a la altura del área visible, por ejemplo, en un monitor con resolución de 1280x1024 píxeles, 100% de altura = 1024 píxeles.

min-height se refiere a la altura total de la página, incluido el contenido, por lo que en una página donde el contenido es mayor que 1024px min-height: 100% se extenderá para incluir todo el contenido.

El otro problema es que el relleno y el borde se agregan a la altura y al ancho en la mayoría de los navegadores modernos, excepto ie6 (ie6 es bastante lógico pero no se ajusta a las especificaciones). Esto se llama el modelo de caja. Entonces si especificas

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

Realmente te dará 100% + 5px + 5px para la altura. Para evitar esto, necesita un contenedor de envoltura.

<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
fuente
44
@Alex: Pero, ¿qué hace que el div interno (el acolchado) sea el 100% de la altura del div externo. Mi experiencia ha sido que solo obtienes una pequeña división corta dentro de una división más grande de altura completa.
Lawrence Dol
8

1. Altura completa con padding

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

2. Altura completa con margin

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

3. Altura completa con border

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

Pegatinas
fuente
7

Esta es una de las idioteces de CSS: todavía tengo que entender el razonamiento (si alguien lo sabe, por favor explique).

100% significa el 100% de la altura del contenedor, a lo que se agrega cualquier margen, borde y relleno. Por lo tanto, es efectivamente imposible obtener un contenedor que llene a su padre y que tenga un margen, borde o relleno.

Tenga en cuenta también que la altura de configuración también es notoriamente inconsistente entre los navegadores.


Otra cosa que he aprendido desde que publiqué esto es que el porcentaje es relativo a la longitud del contenedor , es decir, su ancho, lo que hace que un porcentaje sea aún más inútil para la altura.

Hoy en día, las unidades de ventana vh y vw son más útiles, pero aún no son especialmente útiles para otra cosa que no sean los contenedores de nivel superior.

Lawrence Dol
fuente
No hay razonamiento, solo lo que sucedió cuando los navegadores comenzaron a converger hacia un comportamiento consistente. Mira el libro mencionado en mi respuesta.
Frank Schwieterman
Votado por usar el término correcto. Tex y cualquier administrador de diseño que he visto lo hicieron bien, solo CSS debe ser especial.
maaartinus
5

Otra solución es usar display: table que tiene un comportamiento de modelo de caja diferente.

Puede establecer un alto y ancho para el padre y agregar relleno sin expandirlo. El niño tiene 100% de altura y ancho menos los rellenos.

JSBIN

Otra opción sería utilizar la propiedad de tamaño de caja. El único problema con ambos sería que no funcionan en IE7.

usuario1721135
fuente
4

Otra solución: puede usar unidades de porcentaje para márgenes y tamaños. Por ejemplo:

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

El problema principal aquí es que los márgenes aumentarán / disminuirán ligeramente con el tamaño del elemento padre. Presumiblemente, la funcionalidad que preferiría es que los márgenes permanezcan constantes y que el elemento secundario crezca / se reduzca para completar los cambios en el espaciado. Entonces, dependiendo de qué tan apretada necesite que sea su pantalla, eso podría ser problemático. (También elegiría un margen más pequeño, como 0.3%).

ktbiz
fuente
3

Una solución con flexbox (trabajando en IE11): ( o ver en 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>

(El restablecimiento CSS no es necesariamente importante para el problema real).

La parte importante es flex: 1(en combinación con display: flexen el padre). Curiosamente, la explicación más plausible que conozco sobre cómo funciona la propiedad Flex proviene de una documentación nativa de reacción, así que me refiero a ella de todos modos :

(...) flex: 1, que le dice a un componente que llene todo el espacio disponible, compartido de manera uniforme entre otros componentes con el mismo padre

Putzi San
fuente
2

El ejemplo de Frank me confundió un poco: no funcionó en mi caso porque todavía no entendía el posicionamiento lo suficientemente bien. Es importante tener en cuenta que el elemento contenedor primario debe tener una posición no estática (mencionó esto pero lo pasé por alto y no estaba en su ejemplo).

Aquí hay un ejemplo en el que el niño, dado el relleno y un borde, usa una posición absoluta para llenar al padre al 100%. El padre utiliza el posicionamiento relativo para proporcionar un punto de referencia para la posición del niño mientras permanece en el flujo normal; el siguiente elemento "más contenido" no se ve afectado:

#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>

Un enlace útil para aprender rápidamente el posicionamiento CSS

Peter Tseng
fuente
0

Borde alrededor de div, en lugar del margen del cuerpo de la página

Otra solución: solo quería un borde simple alrededor del borde de mi página, y quería un 100% de altura cuando el contenido era más pequeño que eso.

Border-box no funcionó, y el posicionamiento fijo parecía incorrecto para una necesidad tan simple.

Terminé agregando un borde a mi contenedor, en lugar de depender del margen del cuerpo de la página, se ve así:

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

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

Este es el comportamiento predeterminado de display: blockLa forma más rápida de solucionarlo en 2020 es establecer un display: 'flex'elemento primario y un relleno, por ejemplo, 20 px, entonces todos sus elementos secundarios tendrán una altura del 100% en relación con su altura.

Freestyle09
fuente
0

Para agregar -webkit y -moz sería más apropiado

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

}
</style>
Mujassir Nasir
fuente