¿Cómo forzar que el div hijo sea el 100% de la altura del div padre sin especificar la altura del padre?

535

Tengo un sitio con la siguiente estructura:

<div id="header"></div>

<div id="main">
  <div id="navigation"></div>
  <div id="content"></div>
</div>

<div id="footer"></div>

La navegación está a la izquierda y el contenido div está a la derecha. La información para el contenido div se extrae a través de PHP, por lo que es diferente cada vez.

¿Cómo puedo escalar la navegación verticalmente para que su altura sea la misma que la altura del div de contenido, sin importar qué página esté cargada?

TylerH
fuente
1
Use display table en padre y display table-cell en hijo. Esto hará que el niño sea tan largo como el padre. Ver stackoverflow.com/q/22712489/3429430
user31782
3
Solo puede configurar display: flex; align-items: stretch;el div # main. Y no lo use height: 100%para contenido div #
Igor

Respuestas:

167

NOTA : Esta respuesta es aplicable a los navegadores heredados sin soporte para el estándar Flexbox. Para un enfoque moderno, consulte: https://stackoverflow.com/a/23300532/1155721


Le sugiero que eche un vistazo a las columnas igual altura con CSS entre navegadores y sin trucos .

Básicamente, hacer esto con CSS en una forma compatible con el navegador no es trivial (sino trivial con tablas), así que encuentre una solución preempaquetada adecuada.

Además, la respuesta varía según si desea 100% de altura o igual altura. Por lo general, es igual de altura. Si es 100% de altura, la respuesta es ligeramente diferente.

cletus
fuente
77
Esto parece una buena solución hasta que dibuje un borde, border:1px solid bluepor ejemplo, en container2: el borde azul está en las dos primeras columnas, no en la segunda columna solo como hubiera esperado.
Julien Kronegg
@bfritz, una mejor solución sería usardisplay:table
Siler
538

Para los padres:

display: flex;

Debe agregar algunos prefijos, http://css-tricks.com/using-flexbox/ .

Editar: como señaló @Adam Garner, alinear elementos: estirar; no es necesario. Su uso también es para padres, no para niños. Si desea definir el estiramiento de los niños, use align-self.

.parent {
  background: red;
  padding: 10px;
  display:flex;
}

.other-child {
  width: 100px;
  background: yellow;
  height: 150px;
  padding: .5rem;
}

.child {  
  width: 100px;
  background: blue;
}
<div class="parent">
  <div class="other-child">
    Only used for stretching the parent
  </div>
  <div class="child"></div>
</div>

Aiphee
fuente
3
IE11 no funciona bien con flexbox y alturas. haga clic en "problemas conocidos" aquí: caniuse.com/#feat=flexbox
adamdport
@SuperUberDuper Bueno, puedes usarlo en bootstrap como este: jsfiddle.net/prdwaynk Pero si fuera tú, usaría la base que está lista para producción con flexbox: foundation.zurb.com/sites/docs/xy-grid.html BS4 También tendrá Flexbox, pero todavía está en alfa, y creo que la base es mejor de todos modos.
Aiphee
44
Si está usando align-items: centerel artículo que necesita para estirar las necesidadesalign-self: normal
Dominic
2
Esta no es una respuesta correcta, porque esto necesita establecer la altura de los padres. La pregunta decía 'sin especificar la altura de los padres?'.
SkuraZZ
3
@ Voto de Aiphee porque parece que no viste la parte de no tener que establecer la altura de los padres allí mismo en el texto original de la pregunta, pero tu "solución" hace exactamente eso.
tylerism
99

Este es un tema frustrante que se trata con los diseñadores todo el tiempo. El truco es que debes establecer la altura al 100% en BODY y HTML en tu CSS.

html,body {
    height:100%;
}

Este código aparentemente inútil es definir al navegador lo que significa 100%. Frustrante, sí, pero es la forma más sencilla.

Travis
fuente
99
Excepto que no siempre funciona, por ejemplo, si tiene un elemento posicionado relativo dentro de uno absoluto, ya no obliga a hasLayout.
tim
Además, si desea deshacerse de la barra de desplazamiento en el lado derecho de la ventana (aparece en Firefox v28), déle un respiro a la ventana: html { height: 100%; } body { height: 98%; } .
Chris Middleton
59
Esto solo funciona si todos los padres tienen una altura del 100%, no es suficiente establecer solo el html y el cuerpo, todos los padres deben tener una altura definida.
RaduM
97

Encuentro que configurar las dos columnas en display: table-cell;lugar de float: left;funcionar bien.

Paul Harvey
fuente
10
Los propios MS ya no lo admiten, si eso ayuda a alguien a convencer a sus clientes ...
Heraldmonkey
44
Esta debería ser la respuesta aceptada. Los tiempos han cambiado, esta respuesta funciona en todos los navegadores (con un pequeño capricho en Safari 5.1.17). Dos líneas de CSS e instantáneamente tienes el efecto que estás buscando sin ningún inconveniente que se me ocurra.
callmetwan
77
Levante esta respuesta. Pon tus espaldas en eso muchachos!
Esta es la mejor respuesta. Sí, podemos hacer una tabla para hacer esto, pero no son datos tabulares, sino que tratamos los divs como si fueran celdas de tabla ... ¡Brillante!
Derokorian
Esto realmente me puso en la dirección correcta para un escenario diferente. En caso de que alguien tenga dificultades para trabajar con divs cuadrados que también son contenedores flexibles en Firefox o Edge, solo recuerde configurar el elemento: before para mostrar: table. No me preguntes por qué, pero lo arregla.
CGodo
56

Si no le importa que el div de navegación se recorte en el caso de un div de contenido inesperadamente corto, hay al menos una manera fácil:

#main {
position: relative;
}

#main #navigation {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 10em; /* or whatever */
}

#main #content {
margin: 0;
margin-left: 10em; /* or whatever width you set for #navigation */
}

De lo contrario, está la técnica de columnas falsas .

David dice reinstalar a Mónica
fuente
2
Muchas gracias, me salvaste el día. No sabía que uno podría definir tanto arriba como abajo y funcionaría de esta manera.
rubish
Esto hará que el contenido del contenedor deje de cambiar su tamaño.
DreamWave
+1 porque aborda específicamente la pregunta del OP "¿Cómo forzar la división del niño al 100% de la división del padre sin especificar la altura del padre?" Mi problema no requería columnas (que se mencionan en el detalle de la pregunta pero no en el título principal) sino más bien un div detrás de otro. Esta respuesta funciona en ambas aplicaciones.
Lucas
Esta debería ser la respuesta seleccionada
Gabriel
32
#main {
    overflow: hidden;
}
#navigation, #content {
    margin-bottom: -1000px;
    padding-bottom: 1000px;
}
Roman Kuntyi
fuente
Debo decir que estaba buscando este tipo de solución. Muy simple y tan obvio que nadie lo descubrió. ¡Felicidades @Roman!
Greg0ry
15

usando jQuery:

$(function() {
    function unifyHeights() {
        var maxHeight = 0;
        $('#container').children('#navigation, #content').each(function() {
            var height = $(this).outerHeight();
            // alert(height);
            if ( height > maxHeight ) {
                maxHeight = height;
            }
        });
        $('#navigation, #content').css('height', maxHeight);
    }
    unifyHeights();
});
flavio
fuente
19
Math.max()Sería tu amigo aquí.
alex
1
No pude hacer que el CSS funcionara en todos los casos, realmente solo necesitaba una solución rápida. Puede que no sea el enfoque más estándar , pero este funcionó bien. ¡Gracias! : -]
1
Al usar la cssfunción de JQuery , no puede diferenciar entre la pantalla y los medios impresos, como suele hacer cuando se usan soluciones CSS puras. Por lo tanto, puede tener problemas de impresión.
Julien Kronegg
12

Intenta hacer que el margen inferior sea del 100%.

margin-bottom: 100%;
Tony C
fuente
66
o fondo de relleno: 100%; No es preciso pero funciona bien en algunas situaciones.
Jason
relleno de fondo hace el truco en mi caso. Esta solución es muy similar a lo que publicó @Roman Kuntyi.
Greg0ry
10
#main {
   display: table;
} 
#navigation, #content {
   display: table-cell;
}

Mira este ejemplo .

Sergiu
fuente
Esto es exactamente lo que estaba haciendo, quería agregar una respuesta. También estaba usando height: 100%pero resultó que no era necesario.
jcubic
9

height : <percent>solo funcionará si tiene todos los nodos principales con un porcentaje de altura especificado con una altura fija en píxeles, ems, etc. en el nivel superior. De esa manera, la altura caerá en cascada hasta su elemento.

Puede especificar 100% a html y elementos del cuerpo como @Travis declaró anteriormente para que la altura de la página caiga en cascada a sus nodos.

Lajos Meszaros
fuente
9

Después de una larga búsqueda e intento, nada resolvió mi problema, excepto

style = "height:100%;"

en los niños div

y para los padres apliquen esto

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

Además, estoy usando bootstrap y esto no corrompió la respuesta para mí.

Hakan Fıstık
fuente
1
Tuve que eliminar flex-direction: column;para que esto funcione para mí.
Richard Hedges
6

Según el método descrito en este artículo , he creado una solución menos dinámica:

HTML:

<div id="container3">
    <div id="container2">
        <div id="container1">
            <div id="col1">Column 1</div>
            <div id="col2">Column 2</div>
            <div id="col3">Column 3</div>
        </div>
    </div>
</div>

Menos:

/* Changes these variables to adjust your columns */
@col1Width: 60%;
@col2Width: 1%;
@padding: 0%;

/* Misc variable. Do not change */
@col3Width: 100% - @col1Width - @col2Width;

#container3 {
    float: left;
    width: 100%;
    overflow: hidden;
    background-color: red;
    position: relative;

    #container2 {
        float: left;
        width: 100%;
        position: relative;
        background-color: yellow;
        right: @col3Width;

        #container1 {
            float: left;
            width: 100%;
            position: relative;
            right: @col2Width;
            background-color: green;

            #col1 {
                float: left;
                width: @col1Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding;
                overflow: hidden;
            }

            .col2 {
                float: left;
                width: @col2Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding + @padding * 2;
                overflow: hidden;
            }

            #col3 {
                float: left;
                width: @col3Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding + @padding * 4;
                overflow: hidden;
            }
        }
    }
}
Dmitry Efimenko
fuente
4

Agregar display: gridal padre

Dziamid
fuente
3

Sé que ha pasado mucho tiempo desde que se hizo la pregunta, pero encontré una solución fácil y pensé que alguien podría usarla (perdón por el pobre inglés). Aquí va:

CSS

.main, .sidebar {
    float: none;
    padding: 20px;
    vertical-align: top;
}
.container {
    display: table;
}
.main {
    width: 400px;
    background-color: LightSlateGrey;
    display: table-cell;
}
.sidebar {
    width: 200px;
    display: table-cell;
    background-color: Tomato;
}

HTML

<div class="container clearfix">
    <div class="sidebar">
        simple text here
    </div>
    <div class="main">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam congue, tortor in mattis mattis, arcu erat pharetra orci, at vestibulum lorem ante a felis. Integer sit amet est ac elit vulputate lobortis. Vestibulum in ipsum nulla. Aenean erat elit, lacinia sit amet adipiscing quis, aliquet at erat. Vivamus massa sem, cursus vel semper non, dictum vitae mi. Donec sed bibendum ante.
    </div>
</div>

Ejemplo simple. Tenga en cuenta que puede convertirse en capacidad de respuesta.

Paula Fleck
fuente
Ah, se me olvidó: si desea alinear el contenido de la barra lateral en el medio, simplemente cambie "vertical-align: top" a "vertical-align: middle".
Paula Fleck
2

Mi solución:

$(window).resize(function() {
   $('#div_to_occupy_the_rest').height(
        $(window).height() - $('#div_to_occupy_the_rest').offset().top
    );
});
Rafael Ruiz Muñoz
fuente
1

Hay un poco de contradicción en el título de la pregunta y el contenido. El título habla de un div padre, pero la pregunta hace que parezca que desea que dos div hermanos (navegación y contenido) tengan la misma altura.

¿Desea (a) que tanto la navegación como el contenido tengan el 100% de la altura de main, o (b) desea que la navegación y el contenido tengan la misma altura?

Asumiré (b) ... si es así, no creo que pueda hacerlo dada su estructura de página actual (al menos, no con CSS puro y sin secuencias de comandos). Probablemente necesite hacer algo como:

<main div>
    <content div>
         <navigation div></div>
    </div>
</div>

y configure el div de contenido para que tenga un margen izquierdo del ancho del panel de navegación. De esa manera, el contenido del contenido está a la derecha de la navegación y puede configurar el div de navegación para que sea el 100% de la altura del contenido.

EDITAR: Estoy haciendo esto por completo en mi cabeza, pero probablemente también deba configurar el margen izquierdo del div de navegación en un valor negativo o establecer su izquierda absoluta en 0 para empujarlo hacia el extremo izquierdo. El problema es que hay muchas formas de lograrlo, pero no todas serán compatibles con todos los navegadores.

Paul Abbott
fuente
1

[Refiriéndose al código Less de Dmity en otra respuesta] ¿Supongo que esto es algún tipo de "pseudocódigo"?

Por lo que entiendo, intente usar la técnica de columnas falsas que debería ser la solución.

http://www.alistapart.com/articles/fauxcolumns/

Espero que esto ayude :)

jluna
fuente
44
Según el orden de clasificación de las respuestas, es difícil saber a qué se refiere "esto" ... Supongo que se trata del código de Dmitry. Por lo tanto, este comentario pertenece a un comentario debajo de su respuesta. Y, para su información, no es un pseudocódigo, es un código en el lenguaje Less, una forma de definir CSS de una manera procesal.
PhiLho
1

Este truco funciona: agregar un elemento final en su sección de HTML con un estilo claro: ambos;

    <div style="clear:both;"></div>

Todo lo anterior se incluirá en la altura.

usuario945389
fuente
1

dando position: absolute;al niño trabajado en mi caso

neoDev
fuente
1

Utiliza CSS Flexbox

.flex-container {
  display: flex;
  background-color: DodgerBlue;
}

.flex-container > div {
  background-color: #f1f1f1;
  margin: 10px;
  padding: 20px;
  font-size: 30px;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>

<div class="flex-container">
  <div>1</div>
  <div>2</div>
  <div>3</div>  
</div>

<p>A Flexible Layout must have a parent element with the <em>display</em> property set to <em>flex</em>.</p>

<p>Direct child elements(s) of the flexible container automatically becomes flexible items.</p>

</body>
</html>

Ini
fuente
1

Esta respuesta ya no es ideal ya que CSS flexbox y grid se implementaron en CSS. Sin embargo, sigue siendo una solución de trabajo.

En una pantalla más pequeña, es probable que desee mantener la altura automática ya que col1, col2 y col3 se apilan entre sí.

Sin embargo, después de un punto de interrupción de consulta de medios, desea que aparezcan cols uno al lado del otro con una altura igual para todas las columnas.

1125 px es solo un ejemplo del punto de ruptura del ancho de la ventana, después del cual desea que todas las columnas tengan la misma altura.

<div class="wraper">
    <div class="col1">Lorem ipsum dolor sit amet.</div>
    <div class="col2">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eos laudantium, possimus sed, debitis amet in, explicabo dolor similique eligendi officia numquam eaque quae illo magnam distinctio odio, esse vero aspernatur.</div>
    <div class="col3">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolorem, odio qui praesentium.</div>
</div>

Podría, por supuesto, establecer más puntos de interrupción si lo necesita.

<script>
    $(document).ready(function(){
        $(window).on('load resize', function() {
            let vraperH = $('.wraper').height();
            if (window.innerWidth>= 1125) {
              $('.col1').height(vraperH);
              $('.col2').height(vraperH);
              $('.col3').height(vraperH);
            }
            if (window.innerWidth < 1125) {
              $('.col1').height('auto');
              $('.col2').height('auto');
              $('.col3').height('auto');
            }
        });
    });
</script>
DevWL
fuente
1

Tuve el mismo problema, funcionó según la respuesta de Hakam Fostok, he creado un pequeño ejemplo, en algunos casos podría funcionar sin tener que agregar display: flex;y flex-direction: column;en el contenedor principal

.row {
    margin-top: 20px;
}

.col {
    box-sizing: border-box;
    border: solid 1px #6c757d;
    padding: 10px;
}

.card {
    background-color: #a0a0a0;
    height: 100%;
}

JSFiddle

Builo
fuente
0

Como se mostró anteriormente, flexbox es el más fácil. p.ej.

#main{ display: flex; align-items:center;}

esto alineará todos los elementos secundarios al centro dentro del elemento principal.

Chandan Purohit
fuente
3
esto no responde la pregunta, quieren la misma altura, no centrar el contenido
Ryan M
0

Aquí una demostración antigua basada en el position: absolutecontenedor de contenido yposition: relative contenedor principal.

En cuanto a la forma moderna de hacerlo, las cajas flexibles son las mejores.

WebBrother
fuente
-3

La forma más fácil de hacer esto es simularlo. A List Apart ha cubierto esto ampliamente a lo largo de los años, como en este artículo de Dan Cederholm de 2004 .

Así es como lo hago habitualmente:

<div id="container" class="clearfix" style="margin:0 auto;width:950px;background:white url(SOME_REPEATING_PATTERN.png) scroll repeat-y center top;">
    <div id="navigation" style="float:left;width:190px;padding-right:10px;">
        <!-- Navigation -->
    </div>
    <div id="content" style="float:left;width:750px;">
        <!-- Content -->
    </div>
</div>

Puede agregar fácilmente un encabezado a este diseño envolviendo #container en otro div, incrustando el encabezado div como # hermano del contenedor y moviendo los estilos de margen y ancho al contenedor principal. Además, el CSS debe moverse a un archivo separado y no mantenerse en línea, etc. etc. Finalmente, la clase clearfix se puede encontrar en positioniseverything .

Aaron Brethorst
fuente