html - que - Flex base 100% en la columna Flexbox: altura completa en Firefox, no en Chrome
flex-shrink (4)
Me gustaría una columna de div, de cualquier número, cada una con un ancho del 100% y una altura del 100% de su div principal, de modo que una es visible inicialmente, y las otras desbordan al padre hacia abajo. Establecí los divs para que tengan flex: 0 0 100%;
, dentro de un div principal con display: flex
y flex-direction: column
para lograr esto.
El div principal es en sí mismo de altura desconocida, por lo que también es un elemento secundario de una display: flex
y flex-direction: column
, establecido en flex: 1 0 0
para tomar el espacio restante en su contenedor.
En Firefox, la salida es como me gustaría:
Sin embargo, no en Chrome:
¿Cómo puedo lograr el estilo de Firefox en Chrome, sin Javascript?
Puede ver esto en acción en http://plnkr.co/edit/WnAcmwAPnFaAhqqtwhLL?p=preview , así como la versión correspondiente con flex-direction: row
, que funciona de manera consistente tanto en Firefox como en Chrome.
Como referencia, el CSS completo
.wrapper {
display: flex;
flex-direction: column;
height: 150px;
width: 200px;
border: 4px solid green;
margin-bottom: 20px;
}
.column-parent {
flex: 1 0 0;
display: flex;
flex-direction: column;
border: 2px solid blue;
}
.column-child {
flex: 0 0 100%;
border: 2px solid red;
}
y HTML
<div class="wrapper">
<p>Some content of unknown size</p>
<div class="column-parent">
<div class="column-child">
Should be inside green
</div>
<div class="column-child">
Should be outside green
</div>
</div>
</div>
¿Qué hay de agregar 100% al contenedor?
.column-parent {
flex: 1 0 100%;
}
Y flex-grow a 1 en el elemento contenido sin ajustar la base de flexión:
.column-child {
flex: 1 0 0;
}
Así es como se vería: http://plnkr.co/edit/H25NQxLtbi65oaltNVax?p=preview
Como se indica en la respuesta de Abhitalks, hay un error (o una interpretación diferente del estándar) en la forma en que Chrome maneja el atributo de altura aquí.
He encontrado un truco que funciona tanto en Chrome FF como en IE
El único problema es que debes tener tantas reglas como niños posibles hay.
El truco es establecer la dirección de flexión a la fila, establecer la base de flexión (que ahora es el ancho) al 100%, y luego traducir los elementos
.container {
border: solid 2px blue;
height: 200px;
width: 200px;
display: flex;
flex-direction: column;
position: relative;
}
.filler {
border: solid 1px black;
flex: 0 0 80px;
background-color: lightgreen;
transition: flex 1s;
}
.container:hover .filler {
flex: 0 0 40px;
}
.test {
border: solid 1px red;
flex: 1 0 25px;
display: flex;
flex-direction: row;
position: relative;
}
.child {
background-color: rgba(200, 0, 0, 0.26);
flex: 0 0 100%;
}
.child:nth-child(2) {
background-color: rgba(255, 255, 0, 0.48);
transform: translateX(-100%) translateY(100%);
}
.child:nth-child(3) {
background-color: rgba(173, 216, 230, 0.28);
transform: translateX(-200%) translateY(200%);
}
<div class="container">
<div class="filler"></div>
<div class="filler"></div>
<div class="test">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
</div>
</div>
Si pudiera haber otro hijo, necesitaría una regla n-child (4), y así sucesivamente
He agregado un efecto de desplazamiento para verificar cómo se adapta el tamaño
Esto parece ser un error con Chrome. Similar a los informados aquí (número 428049) y quizás relacionado (número 346275) .
- Browsers are supposed to resolve percentages on the flex item''s child, *if* its flex-basis is definite. - Gecko is *always* resolving percentages regardless of the flex-basis. - Chrome is *never* resolving percentages, regardless of the flex-basis.
En resumen, Chrome no resuelve porcentajes de alturas en el elemento de flex-item ( incluso si el propio elemento es un elemento flexible ), mientras que el resto de navegadores sí lo hace.
Esto se puede demostrar en el siguiente fragmento: ( Violín aquí )
* { box-sizing: border-box; margin: 0; padding: 0; }
div.wrap {
height: 120px; width: 240px; margin: 0px 12px;
border: 1px solid blue; float: left;
display: flex; flex-direction: column;
}
div.parent {
flex: 0 0 100%;
border: 1px solid green;
display: flex; flex-direction: column;
}
div.item {
flex: 0 0 100%;
border: 1px solid red;
}
<div class="wrap">
<div class="item">a</div>
<div class="item">b</div>
<div class="item">c</div>
</div>
<div class="wrap">
<div class="parent">
<div class="item">a</div>
<div class="item">b</div>
<div class="item">c</div>
</div>
</div>
El segundo div
debería mostrar el mismo comportamiento que el primero. Otros navegadores (IE11, Edge, FF39) lo muestran correctamente. Chrome falla aquí y no resuelve div.item
correctamente. Necesita una altura fija en su elemento primario, sin lo cual utiliza min-content
como su altura y, por lo tanto, no se desborda.
Mientras que, en el primer div
, los div.item
div
se resuelven correctamente y se desbordan en consecuencia. Esto se debe a que hay una altura fija en el padre (es decir, div.wrap
)
Solución posible:
Como solución, si está seguro de tener solo dos elementos ( p
y div
) dentro de su envoltorio, entonces podría darles una altura del 50%
. .column-parent
proporcionar una height:50%
a su .column-parent
. Chrome necesita una altura fija en el padre como se demostró anteriormente.
Entonces todo funcionará como lo necesites.
Demo Fiddle: http://jsfiddle.net/abhitalks/kqncm65n/
CSS relevante :
.wrapper > p { flex: 0 0 50%; } /* this can be on flex-basis */
.column-parent {
flex: 1 0 auto; height: 50%; /* but, this needs to be fixed height */
display: flex; flex-direction: column;
border: 2px solid blue;
}
.column-child {
flex: 0 0 100%; /* this flex-basis is then enough */
border: 2px solid red;
}
PD: También parece haber diferencias en la forma en que jsfiddle y plnkr rinden. No sé por qué, pero a veces obtengo resultados diferentes.
Mi respuesta anterior es un truco que explota una configuración particular del diseño deseado.
Una manera alternativa, más general, de evitar este error de Chrome es usar un elemento intermedio en el diseño, y establecer el tamaño de este elemento usando top: 0px y bottom: 0px. (en lugar de altura: 100%) Todavía hay un error en la forma en que Chrome maneja el cálculo, que necesita una animación falsa para que se ajuste correctamente
.container {
border: solid 2px blue;
height: 200px;
width: 200px;
display: flex;
flex-direction: column;
position: relative;
}
.filler {
border: solid 1px black;
flex: 0 0 94px;
background-color: lightgreen;
transition: 1s;
}
.container:hover .filler {
flex: 0 0 50px;
}
.test {
border: solid 1px red;
flex: 1 0 25px;
display: flex;
flex-direction: row;
position: relative;
}
@-webkit-keyframes adjust2 {
0% {flex-basis: 100%;}
100% {flex-basis: 100.1%;}
}
.child {
background-color: rgba(200, 0, 0, 0.26);
width: 100%;
height: 100%;
flex: 1 0 100%;
-webkit-animation: adjust2 1s infinite; /* only needed for webkit bug */
}
.intermediate {
width: 100%;
position: absolute;
top: 0px;
bottom: 0px;
display: flex;
flex-direction: column;
}
.child:nth-child(n+2) {
background-color: rgba(255, 255, 0, 0.48);
}
.child:nth-child(n+3) {
background-color: rgba(173, 216, 230, 0.28);
}
<div class="container">
<div class="filler"></div>
<div class="test">
<div class="intermediate">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</div>