una toda tamaño que porcentaje pantalla pagina ocupe hacer calcular body automatico alto css css3 google-chrome webkit flexbox

css - toda - height de una pagina



Chrome/Safari no llena el 100% de la altura del padre flexible (4)

Quiero tener un menú vertical con una altura específica.

Cada niño debe llenar la altura del padre y tener texto alineado en el medio.

El número de hijos es aleatorio, así que tengo que trabajar con valores dinámicos.

Div .container contiene un número aleatorio de hijos ( .item ) que siempre tienen que llenar la altura del padre. Para lograr eso usé flexbox.

Para hacer enlaces con texto alineado al medio, estoy usando display: table-cell técnica display: table-cell . Pero usar pantallas de mesa requiere usar una altura del 100%.

Mi problema es que .item-inner { height: 100% } no funciona en webkit (Chrome).

  1. ¿Hay alguna solución para este problema?
  2. ¿O hay una técnica diferente para hacer que todos los .item llenen la altura del padre con el texto alineado verticalmente al medio?

Ejemplo aquí jsFiddle, debe verse en Firefox y Chrome

.container { height: 20em; display: flex; flex-direction: column; border: 5px solid black } .item { flex: 1; border-bottom: 1px solid white; } .item-inner { height: 100%; width: 100%; display: table; } a { background: orange; display: table-cell; vertical-align: middle; }

<div class="container"> <div class="item"> <div class="item-inner"> <a>Button</a> </div> </div> <div class="item"> <div class="item-inner"> <a>Button</a> </div> </div> <div class="item"> <div class="item-inner"> <a>Button</a> </div> </div> </div>


Solución

Use contenedores flexibles anidados.

Deshágase de las alturas porcentuales. Deshágase de las propiedades de la tabla. Deshágase de vertical-align . Evitar el posicionamiento absoluto. Solo quédate con flexbox hasta el final.

Aplique display: flex al elemento flex ( .item ), convirtiéndolo en un contenedor flexible. Esto establece automáticamente align-items: stretch , que le dice al niño ( .item-inner ) que expanda la altura completa del padre.

Importante: elimine las alturas especificadas de los elementos flexibles para que este método funcione. Si un niño tiene una altura especificada (por ejemplo, height: 100% ), ignorará los elementos de align-items: stretch proveniente del padre. Para que el stretch predeterminado funcione, la altura del niño debe calcularse en auto (explicación completa ).

Pruebe esto (sin cambios en HTML):

.container { display: flex; flex-direction: column; height: 20em; border: 5px solid black } .item { display: flex; /* new; nested flex container */ flex: 1; border-bottom: 1px solid white; } .item-inner { display: flex; /* new; nested flex container */ flex: 1; /* new */ /* height: 100%; <-- remove; unnecessary */ /* width: 100%; <-- remove; unnecessary */ /* display: table; <-- remove; unnecessary */ } a { display: flex; /* new; nested flex container */ flex: 1; /* new */ align-items: center; /* new; vertically center text */ background: orange; /* display: table-cell; <-- remove; unnecessary */ /* vertical-align: middle; <-- remove; unnecessary */ }

<div class="container"> <div class="item"> <div class="item-inner"> <a>Button</a> </div> </div> <div class="item"> <div class="item-inner"> <a>Button</a> </div> </div> <div class="item"> <div class="item-inner"> <a>Button</a> </div> </div> </div>

jsFiddle demo

Explicación

Mi problema es que .item-inner { height: 100% } no funciona en webkit (Chrome).

No funciona porque está utilizando el porcentaje de altura de una manera que no se ajusta a la implementación tradicional de la especificación.

10.5 Altura del contenido: la propiedad de height

porcentaje
Especifica un porcentaje de altura. El porcentaje se calcula con respecto a la altura del bloque que contiene la caja generada. Si la altura del bloque contenedor no se especifica explícitamente y este elemento no está en una posición absoluta, el valor se calcula como auto .

auto
La altura depende de los valores de otras propiedades.

En otras palabras, para que la altura porcentual funcione en un elemento secundario en flujo, el elemento primario debe tener una altura establecida.

En su código, el contenedor de nivel superior tiene una altura definida: .container { height: 20em; } .container { height: 20em; }

El contenedor de tercer nivel tiene una altura definida: .item-inner { height: 100%; } .item-inner { height: 100%; }

Pero entre ellos, el contenedor de segundo nivel - .item - no tiene una altura definida. Webkit ve eso como un eslabón perdido.

.item-inner le dice a Chrome: dame height: 100% . Chrome mira al padre ( .item ) como referencia y responde: ¿ 100% de qué? No veo nada (ignorando la regla flex: 1 que está allí). Como resultado, aplica height: auto (altura de contenido), de acuerdo con la especificación.

Firefox, por otro lado, ahora acepta la altura flexible de un padre como referencia para la altura porcentual del niño. IE11 y Edge también aceptan alturas flexibles.

Además, Chrome aceptará flex-grow como una referencia principal adecuada si se usa junto con flex-basis (cualquier valor numérico funciona ( auto no), incluida flex-basis: 0 ). Al escribir estas líneas, sin embargo, esta solución falla en Safari.

#outer { display: flex; flex-direction: column; height: 300px; background-color: white; border: 1px solid red; } #middle { flex-grow: 1; flex-basis: 1px; background-color: yellow; } #inner { height: 100%; background-color: lightgreen; }

<div id="outer"> <div id="middle"> <div id="inner"> INNER </div> </div> </div>

Cuatro soluciones

1. Especifique una altura en todos los elementos principales

Una solución confiable para varios navegadores es especificar una altura en todos los elementos principales. Esto evita enlaces faltantes, que los navegadores basados ​​en Webkit consideran una violación de la especificación.

Tenga en cuenta que min-height max-height no son aceptables. Debe ser la propiedad de height .

Más detalles aquí: trabajar con la propiedad de height CSS y los valores de porcentaje

2. Posicionamiento relativo y absoluto de CSS

Aplicar position: relative al padre y position: absolute al hijo.

Tamaño del niño con height: 100% y width: 100% , o utilice las propiedades de desplazamiento: top: 0 , right: 0 , bottom: 0 , left: 0 .

Con posicionamiento absoluto, la altura porcentual funciona sin una altura especificada en el padre.

3. Eliminar contenedores HTML innecesarios (recomendado)

¿Hay necesidad de dos contenedores alrededor del button ? ¿Por qué no eliminar .item o .item-inner , o ambos? Aunque los elementos de button veces fallan como contenedores flexibles , pueden ser elementos flexibles. Considere convertir el button un elemento secundario de .container o .item , y eliminar el marcado gratuito.

Aquí hay un ejemplo:

.container { height: 20em; display: flex; flex-direction: column; border: 5px solid black } a { flex: 1; background: orange; border-bottom: 1px solid white; display: flex; /* nested flex container (for aligning text) */ align-items: center; /* center text vertically */ justify-content: center; /* center text horizontally */ }

<div class="container"> <a>Button</a> <a>Button</a> <a>Button</a> </div>

4. Contenedores flexibles anidados (recomendado)

Deshágase de las alturas porcentuales. Deshágase de las propiedades de la tabla. Deshágase de vertical-align . Evitar el posicionamiento absoluto. Solo quédate con flexbox hasta el final.

Aplique display: flex al elemento flex ( .item ), convirtiéndolo en un contenedor flexible. Esto establece automáticamente align-items: stretch , que le dice al niño ( .item-inner ) que expanda la altura completa del padre.

Importante: elimine las alturas especificadas de los elementos flexibles para que este método funcione. Si un niño tiene una altura especificada (por ejemplo, height: 100% ), ignorará los elementos de align-items: stretch proveniente del padre. Para que el stretch predeterminado funcione, la altura del niño debe calcularse en auto (explicación completa ).

Pruebe esto (sin cambios en HTML):

.container { display: flex; flex-direction: column; height: 20em; border: 5px solid black } .item { display: flex; /* new; nested flex container */ flex: 1; border-bottom: 1px solid white; } .item-inner { display: flex; /* new; nested flex container */ flex: 1; /* new */ /* height: 100%; <-- remove; unnecessary */ /* width: 100%; <-- remove; unnecessary */ /* display: table; <-- remove; unnecessary */ } a { display: flex; /* new; nested flex container */ flex: 1; /* new */ align-items: center; /* new; vertically center text */ background: orange; /* display: table-cell; <-- remove; unnecessary */ /* vertical-align: middle; <-- remove; unnecessary */ }

<div class="container"> <div class="item"> <div class="item-inner"> <a>Button</a> </div> </div> <div class="item"> <div class="item-inner"> <a>Button</a> </div> </div> <div class="item"> <div class="item-inner"> <a>Button</a> </div> </div> </div>

jsFiddle


Para Safari móvil Hay una solución de navegador. necesita agregar -webkit-box para dispositivos iOS.

Ex.

display: flex; display: -webkit-box; flex-direction: column; -webkit-box-orient: vertical; -webkit-box-direction: normal; -webkit-flex-direction: column; align-items: stretch;

si usa elementos de align-items: stretch; propiedad del elemento primario, elimine la height : 100% del elemento secundario.



Tuve un problema similar en iOS 8, 9 y 10 y la información anterior no pudo solucionarlo, sin embargo, descubrí una solución después de un día de trabajar en esto. De acuerdo, no funcionará para todos, pero en mi caso mis artículos se apilaron en una columna y tenían una altura de 0 cuando debería haber sido altura de contenido. Cambiar el CSS para que sea fila y ajuste solucionó el problema. Esto solo funciona si tiene un solo elemento y están apilados, pero como me llevó un día descubrirlo, ¡pensé que debería compartir mi solución!

.wrapper { flex-direction: column; // <-- Remove this line flex-direction: row; // <-- replace it with flex-wrap: wrap; // <-- Add wrapping } .item { width: 100%; }