auto-fill frente a auto-fit
Las dos repeticiones automáticas producen el mismo resultado casi siempre y resultados opuestos cuando sobran pistas. El mecanismo del colapso, un ejemplo con números y cuándo elegir cada una.
auto-fill y auto-fit se explican en todas partes como si fueran casi lo mismo, y con diez elementos en la rejilla lo son: producen exactamente el mismo resultado. La diferencia aparece solo cuando caben más pistas de las que hay elementos, y entonces es dramática. Como ese caso se da al final de una lista filtrada, en un estado con pocos resultados o en un contenedor ancho, es un bug que llega en producción y no en desarrollo.
- Calcular cuántas pistas genera una repetición automática.
- Describir el colapso de pistas vacías de
auto-fity qué pasa con sus gaps. - Predecir el resultado de ambos con dos elementos en un contenedor ancho.
- Elegir entre los dos según lo que deba pasar cuando falten elementos.
Cuántas pistas se generan y qué pasa con las vacías
Con repeat(auto-fill, X) o repeat(auto-fit, X), el número de repeticiones no lo escribes tú: es el mayor entero positivo que no hace desbordar el contenedor, contando los gaps.
Contenedor de 1000px, gap: 20px, pistas de minmax(200px, 1fr). Con n pistas, el ancho ocupado en el mínimo es 200n + 20(n − 1). Para n = 4: 800 + 60 = 860, cabe. Para n = 5: 1000 + 80 = 1080, no cabe. Se generan cuatro pistas.
Hasta aquí auto-fill y auto-fit hacen exactamente lo mismo. Ambos generan cuatro. La diferencia viene después.
Si el contenedor no tiene un tamaño ni un tamaño máximo determinable en ese eje, la repetición automática genera una sola pista. Ocurre con rejillas dentro de contenedores de ancho intrínseco, como un elemento flex con flex: 0 0 auto o un inline-grid. El síntoma es una rejilla de una columna que no entiendes.
La divergencia está en qué se hace con las pistas que no reciben ningún elemento. Con auto-fill, las cuatro pistas existen y ocupan espacio, tengan contenido o no. Las que quedan vacías siguen recibiendo su parte del reparto flexible.
Con auto-fit, las cuatro pistas se generan igual, pero después las que han quedado vacías se colapsan a cero. Y no solo eso: los dos gaps que rodeaban a una pista colapsada se funden en uno solo. El resultado es que las pistas que sí tienen contenido se reparten todo el espacio del contenedor.
La especificación es literal: auto-fit se comporta como auto-fill, salvo que después de colocar los elementos las pistas vacías se tratan como si tuvieran un tamaño fijo de cero.
El ejemplo con números
Mismo contenedor de 1000px, gap: 20px, minmax(200px, 1fr), pero solo dos elementos.
.rellenar {
display: grid;
inline-size: 1000px;
gap: 20px;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.ajustar {
display: grid;
inline-size: 1000px;
gap: 20px;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
<div class="rellenar"><div>Uno</div><div>Dos</div></div>
<div class="ajustar"><div>Uno</div><div>Dos</div></div>
Con auto-fill: cuatro pistas, tres gaps de 20px. Espacio libre: 1000 − 60 = 940, repartido entre cuatro pistas de 1fr: 235px cada una. Los dos elementos miden 235px y ocupan las dos primeras pistas. Las otras dos siguen ahí, vacías, ocupando 490px a la derecha. Visualmente: dos cajas estrechas alineadas a la izquierda y medio contenedor en blanco.
Con auto-fit: las dos pistas vacías colapsan a cero y sus gaps se funden. Quedan dos pistas y un gap. Espacio libre: 1000 − 20 = 980, repartido entre dos: 490px cada una. Los dos elementos miden 490px y llenan el contenedor entero. Visualmente: dos cajas anchas de borde a borde.
La diferencia es de 235px frente a 490px por elemento. No es un matiz.
Cuál elegir
La pregunta correcta es qué debe pasar cuando hay menos elementos de los que caben.
Elige auto-fill cuando quieras preservar la retícula. Los elementos conservan su tamaño previsto y el hueco queda visible. Es lo correcto en una rejilla de tarjetas de producto, en una galería paginada o en cualquier caso donde una tarjeta de 490px se vería absurda al lado de una fila de tarjetas de 235px de la página anterior. También es lo correcto si vas a añadir elementos dinámicamente: el layout no da un salto al llegar el tercero.
Elige auto-fit cuando quieras que el contenido siempre ocupe todo el ancho. Es lo correcto en paneles de estadísticas, en listas de filtros o en cualquier caso donde una fila incompleta se vería peor que unas cajas más anchas de lo previsto.
El caso extremo de auto-fit es tener un solo elemento: se lleva el 100% del contenedor. Una tarjeta de producto de 1400px de ancho porque la búsqueda devolvió un resultado es un fallo visual clásico y muy visible. Si usas auto-fit, pon un tope: grid-template-columns: repeat(auto-fit, minmax(200px, 24rem)) o justify-content: start para que las pistas no se estiren.
Dos errores de sintaxis frecuentes
repeat(auto-fill, 1fr) es inválido. La repetición automática exige que la pista tenga un mínimo determinable, porque para contar cuántas caben hay que saber cuánto ocupa cada una como mínimo. Un fr no lo dice. Por el mismo motivo, repeat(auto-fill, minmax(min-content, 1fr)) tampoco vale.
/* Inválido: se descarta la declaración entera */
.a { grid-template-columns: repeat(auto-fill, 1fr); }
.b { grid-template-columns: repeat(auto-fill, minmax(auto, 1fr)); }
/* Válido */
.c { grid-template-columns: repeat(auto-fill, 200px); }
.d { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
El segundo error es el desbordamiento en contenedores estrechos. Con minmax(200px, 1fr) y un contenedor de 180px, se genera una pista de 200px que desborda: el mínimo es un suelo y no se negocia. La corrección es hacer que el mínimo también ceda:
/* El mínimo es 200px, salvo que el contenedor sea más estrecho */
.rejilla {
grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr));
}
Fíjate en que min(200px, 100%) sigue siendo un mínimo determinable, así que la repetición automática lo acepta. Es la variante que deberías escribir por defecto.
Lo interesante de esta pareja no es la mecánica del colapso, que es sencilla, sino que sean dos palabras clave en lugar de una. El grupo de trabajo podría haber elegido un comportamiento y ya está; que decidiera exponer los dos significa que reconoció que aquí no hay una respuesta técnicamente superior, sino dos intenciones de diseño legítimas y opuestas. auto-fill dice “la retícula es la verdad y los elementos la ocupan”. auto-fit dice “los elementos son la verdad y la retícula se adapta”. Es exactamente la misma tensión que ya viste en flex-basis: 0 frente a auto, y que reaparecerá en subgrid frente a rejillas independientes: quién manda, el contenedor o el contenido. Verás esa dicotomía una y otra vez, y conviene tenerla nombrada, porque casi ninguna documentación la enuncia y sin ella cada par de opciones parece un capricho que hay que memorizar. La consecuencia práctica es un hábito de lectura: cuando te encuentres dos valores de CSS que parecen hacer lo mismo, no busques cuál es mejor. Busca en qué caso límite divergen, porque ese caso límite es la decisión de diseño que la especificación te está pidiendo que tomes, y casi siempre está en el extremo donde hay muy pocos elementos o muchísimos.
- Monta las dos rejillas del ejemplo con dos elementos y mide en DevTools el ancho de cada uno.
- Ve añadiendo elementos de uno en uno y anota en qué momento las dos versiones dejan de distinguirse.
- Activa el superpuesto de grid en DevTools con
auto-fity comprueba que las pistas vacías no se dibujan. - Provoca el desbordamiento con un contenedor de 180px y arréglalo con
min(200px, 100%). - Escribe una versión de
auto-fitcon tope que no produzca una tarjeta gigante cuando solo hay un elemento.