css tamaño - Chrome / Safari no se completa al 100% de la altura del elemento flexible





height una (3)


Solución: elimine la height: 100% en .item-inner y agregue display: flex in .item

Demostración: https://codepen.io/tronghiep92/pen/NvzVoo

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

Cada niño debe llenar el alto del padre y tener texto alineado a la mitad.

La cantidad de niños es aleatoria, así que tengo que trabajar con valores dinámicos.

El .container Div contiene un número aleatorio de elementos .item ( .item ) que siempre deben llenar la altura del elemento principal. Para lograr eso utilicé flexbox.

Para hacer enlaces con el texto alineado al centro, estoy usando display: table-cell técnica de display: table-cell . Pero el uso de pantallas de tabla requiere el uso de 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 elemento primario con el texto vertical alineado al centro?

Ejemplo aquí jsFiddle, debería 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>




El problema

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

No está funcionando porque está utilizando la altura del porcentaje 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 una altura de porcentaje. 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á completamente posicionado, el valor se calcula en auto .

auto
La altura depende de los valores de otras propiedades.

En otras palabras, para que la altura porcentual funcione en un hijo en flujo, el padre 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 lo ve como un eslabón perdido.

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

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

Además, Chrome aceptará flex-grow como una referencia parental adecuada si se utiliza junto con flex-basis (cualquier valor funciona, 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>

Soluciones

1. Especifique una altura en todos los elementos principales

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

Tenga en cuenta que min-height y 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 para el niño.

Tamaño del niño con la height: 100% y width: 100% , o use las propiedades de compensación: top: 0 , right: 0 , bottom: 0 , left: 0 .

Con un posicionamiento absoluto, la altura porcentual funciona sin una altura especificada en el elemento primario.

3. Eliminar los contenedores HTML innecesarios (recomendado)

¿Hay una 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 hacer que el button un hijo 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. Envases flexibles anidados (recomendado)

Deshágase de las alturas porcentuales. Deshágase de las propiedades de la tabla. Deshacerse de vertical-align . Evita el posicionamiento absoluto. Solo quédese con flexbox todo el tiempo.

Aplicar display: flex al elemento flexible ( .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 elemento principal.

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




Hazlo simple: DEMO

section {
  display: flex;
  flex-flow: column;
  height: 300px;
}
header {
  background: tomato;
/* no flex rules, it will grow */
}
div {
  flex: 1;/* 1 and it will fill whole space left if no flex value are set to other children*/
  background: gold;
  overflow: auto;
}
footer {
  background: lightgreen;
  min-height: 60px; /* min-height has its purpose :) , unless you meant height*/
}




css css3 google-chrome webkit flexbox