html - template - Cuando los elementos de flexbox se envuelven en modo columna, el contenedor no aumenta su ancho
grid-template-columns (4)
El problema
Esto parece una deficiencia fundamental en el diseño flexible.
Un contenedor flexible en la dirección de la columna no se expandirá para acomodar columnas adicionales.
(Esto no es un problema en
flex-direction: row
).
Esta pregunta se ha hecho muchas veces (ver la lista a continuación), sin respuestas claras en CSS.
Es difícil identificar esto como un error porque el problema ocurre en todos los principales navegadores. Pero plantea la pregunta:
¿Cómo es posible que todos los principales navegadores obtuvieran el contenedor flexible para expandirse en la envoltura en dirección de fila pero no en dirección de columna?
Uno pensaría que al menos uno de ellos lo haría bien. Solo puedo especular sobre la razón. Tal vez fue una implementación técnicamente difícil y se archivó para esta iteración.
ACTUALIZACIÓN: El problema parece resolverse en Edge v16.
Ilustración del problema
El OP creó una demostración útil que ilustra el problema. Lo estoy copiando aquí: http://jsfiddle.net/nwccdwLw/1/
Opciones de solución
Soluciones de Hacky de la comunidad de Stack Overflow:
-
"Parece que este problema no se puede resolver solo con CSS, por lo que le propongo una solución JQuery".
-
"Es curioso que la mayoría de los navegadores no hayan implementado contenedores flexibles de columnas correctamente, pero el soporte para los modos de escritura es razonablemente bueno. Por lo tanto, puede usar un contenedor flexible de filas con un modo de escritura vertical".
Más análisis
-
La respuesta de Mark Amery
Otras publicaciones que describen el mismo problema
- El ancho del contenedor de caja flexible no crece
- ¿Cómo puedo hacer una pantalla: el contenedor flexible se expande horizontalmente con su contenido envuelto?
- Flujo flexible: envoltura de columna. ¿Cómo establecer el ancho del contenedor igual al contenido?
- ¿Errores de envoltura de columna de flujo flexible Flexbox en cromo?
- ¿Cómo uso "flex-flow: column wrap"?
- El contenedor flexible no se expande cuando el contenido se envuelve en una columna
- flujo flexible: ajuste de columna, en una caja flexible que causa el desbordamiento del contenedor principal
- El contenedor html flexbox no se expande sobre niños envueltos
- ¿Contenedor de Flexbox y niños rebosantes de flex?
- ¿Cómo puedo hacer un contenedor flexbox que se estire para caber en los artículos envueltos?
- Contenedor flexible que calcula una columna, cuando hay varias columnas
- Hacer contenedor de ancho completo con flex
- ¿Es posible cambiar el tamaño del contenedor Flexbox?
- Flex-Wrap Inside Flex-Grow
- Flexbox crece para contener
- ¿Expandir el elemento flexbox a su contenido?
- estiramiento de columna flexbox para adaptarse al contenido
- https://stackoverflow.com/q/48406237/3597276
- flujo flexible: el ajuste de la columna no estira el ancho del elemento principal
- ¿Por qué mi <ul> no amplía el ancho para cubrir todos los <li>?
- ¿Cómo ajustar el ancho cuando las columnas flexbox se ajustan?
- ¿Flexbox wrap no aumenta el ancho del padre?
Estoy trabajando en un diseño de caja flexible anidado que debería funcionar de la siguiente manera:
El nivel más externo (
ul#main
) es una lista horizontal que debe expandirse a la derecha cuando se le agregan más elementos.
Si crece demasiado, debe haber una barra de desplazamiento horizontal.
#main {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
overflow-x: auto;
/* ...and more... */
}
Cada elemento de esta lista (
ul#main > li
) tiene un encabezado (
ul#main > li > h2
) y una lista interna (
ul#main > li > ul.tasks
).
Esta lista interna es vertical y debe ajustarse en columnas cuando sea necesario.
Al envolver en más columnas, su ancho debe aumentar para dejar espacio para más artículos.
Este aumento de ancho debería aplicarse también al elemento contenedor de la lista externa.
.tasks {
flex-direction: column;
flex-wrap: wrap;
/* ...and more... */
}
Mi problema es que las listas internas no se ajustan cuando la altura de la ventana es demasiado pequeña. He intentado muchas manipulaciones con todas las propiedades de flex, tratando de seguir las pautas de CSS-Tricks meticulosamente, pero no tuve suerte.
Este JSFiddle muestra lo que tengo hasta ahora.
Resultado esperado (lo que quiero) :
Resultado real (lo que obtengo) :
Resultado anterior (lo que obtuve en 2015) :
ACTUALIZAR
Después de una investigación, esto comienza a parecer un problema mayor. Todos los principales navegadores se comportan de la misma manera , y no tiene nada que ver con que mi diseño de Flexbox esté anidado. Incluso los diseños de columna de flexbox más simples se niegan a aumentar el ancho de la lista cuando los elementos se ajustan.
Este
otro JSFiddle
demuestra claramente el problema.
En las versiones actuales de Chrome, Firefox e IE11, todos los elementos se ajustan correctamente;
la altura de la lista aumenta en modo
row
, pero su ancho no aumenta en modo
column
.
Además, no hay reflujo inmediato de elementos cuando se cambia la altura de un modo de
column
, pero sí en modo
row
.
Sin embargo, las especificaciones oficiales (ver específicamente el ejemplo 5) parecen indicar que lo que quiero hacer debería ser posible.
¿Alguien puede encontrar una solución a este problema?
ACTUALIZACIÓN 2
Después de mucho experimentar usando JavaScript para actualizar la altura y el ancho de varios elementos durante los eventos de cambio de tamaño, he llegado a la conclusión de que es demasiado complejo y demasiados problemas tratar de resolverlo de esa manera. Además, agregar JavaScript definitivamente rompe el modelo flexbox, que debe mantenerse lo más limpio posible.
Por ahora, vuelvo a
overflow-y: auto
lugar de
flex-wrap: wrap
para que el contenedor interno se desplace verticalmente cuando sea necesario.
No es bonito, pero es una forma de avanzar que al menos no rompe demasiado la usabilidad.
Como todavía no se sugirió ninguna solución o solución adecuada, logré obtener el comportamiento solicitado con un enfoque un poco diferente. En lugar de separar el diseño en 3 divs diferentes, estoy agregando todos los elementos en 1 div y creando la separación con algunos divs más en el medio.
La solución propuesta está codificada, suponiendo que tengamos 3 secciones, pero puede extenderse a una genérica. La idea principal es explicar cómo podemos lograr este diseño.
- Agregar todos los artículos en 1 contenedor div que usa flex para envolver los artículos
- El primer elemento de cada "contenedor interno" (lo llamaré una sección) tendrá una clase, que nos ayuda a hacer algunas manipulaciones que crean la separación y el estilo de cada sección.
-
Usando
:before
en cada primer elemento, podemos ubicar el título de cada sección. -
El uso del
space
crea un espacio entre las secciones. -
Como el
space
no cubrirá la altura completa de la sección, también estoy agregando:after
de las secciones, así que colóquelo con una posición absoluta y fondo blanco. -
Para diseñar el color de fondo de cada sección, agrego otro div dentro del primer elemento de cada sección.
Estaré en posición absoluta y también tendré
z-index: -1
. - Para obtener el ancho correcto de cada fondo, estoy usando JS, establezco el ancho correcto y también agrego un oyente para cambiar el tamaño.
function calcWidth() {
var size = $(document).width();
var end = $(".end").offset().left;
var todoWidth = $(".doing-first").offset().left;
$(".bg-todo").css("width", todoWidth);
var doingWidth = $(".done-first").offset().left - todoWidth;
$(".bg-doing").css("width", doingWidth);
var doneWidth = $(".end").offset().left - $(".done-first").offset().left;
$(".bg-done").css("width", doneWidth + 20);
}
calcWidth();
$(window).resize(function() {
calcWidth();
});
.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 120px;
align-content: flex-start;
padding-top: 30px;
overflow-x: auto;
overflow-y: hidden;
}
.item {
width: 200px;
background-color: #e5e5e5;
border-radius: 5px;
height: 20px;
margin: 5px;
position: relative;
box-shadow: 1px 1px 5px 0px rgba(0, 0, 0, 0.75);
padding: 5px;
}
.space {
height: 150px;
width: 10px;
background-color: #fff;
margin: 10px;
}
.todo-first:before {
position: absolute;
top: -30px;
height: 30px;
content: "To Do (2)";
font-weight: bold;
}
.doing-first:before {
position: absolute;
top: -30px;
height: 30px;
content: "Doing (5)";
font-weight: bold;
}
.doing-first:after,
.done-first:after {
position: absolute;
top: -35px;
left: -25px;
width: 10px;
height: 180px;
z-index: 10;
background-color: #fff;
content: "";
}
.done-first:before {
position: absolute;
top: -30px;
height: 30px;
content: "Done (3)";
font-weight: bold;
}
.bg-todo {
position: absolute;
background-color: #FFEFD3;
width: 100vw;
height: 150px;
top: -30px;
left: -10px;
z-index: -1;
}
.bg-doing {
position: absolute;
background-color: #EFDCFF;
width: 100vw;
height: 150px;
top: -30px;
left: -15px;
z-index: -1;
}
.bg-done {
position: absolute;
background-color: #DCFFEE;
width: 10vw;
height: 150px;
top: -30px;
left: -15px;
z-index: -1;
}
.end {
height: 150px;
width: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="item todo-first">
<div class="bg-todo"></div>
Drink coffee
</div>
<div class="item">Go to work</div>
<div class="space"></div>
<div class="item doing-first">
<div class="bg-doing"></div>
1
</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="space"></div>
<div class="item done-first">
<div class="bg-done"></div>
1
</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="end"></div>
</div>
Llegó tarde a la fiesta, pero aún se encontraba con este problema AÑOS más tarde. Terminé buscando una solución usando la cuadrícula. En el contenedor puedes usar
display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(6, auto);
Tengo un ejemplo en CodePen que alterna entre el problema de flexbox y la corrección de la cuadrícula: https://codepen.io/MandeeD/pen/JVLdLd
Posible solución JS ..
var ul = $("ul.ul-to-fix");
if(ul.find("li").length>{max_possible_rows)){
if(!ul.hasClass("width-calculated")){
ul.width(ul.find("li").eq(0).width()*ul.css("columns"));
ul.addClass("width-calculated");
}
}