wandres.dev
GRID I · El sistema de dos dimensiones

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.

⏱ 17 min

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.

🎯 Al terminar esta lección sabrás
  • Calcular cuántas pistas genera una repetición automática.
  • Describir el colapso de pistas vacías de auto-fit y 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.

📝
Sin tamaño definido no hay repetición

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.

⚠️
auto-fit con un solo elemento

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.

auto-fit toma una decisión de diseño por ti, y esa es exactamente la pregunta que hay que hacerse

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.

⚔️ Ve la diferencia
  1. Monta las dos rejillas del ejemplo con dos elementos y mide en DevTools el ancho de cada uno.
  2. Ve añadiendo elementos de uno en uno y anota en qué momento las dos versiones dejan de distinguirse.
  3. Activa el superpuesto de grid en DevTools con auto-fit y comprueba que las pistas vacías no se dibujan.
  4. Provoca el desbordamiento con un contenedor de 180px y arréglalo con min(200px, 100%).
  5. Escribe una versión de auto-fit con tope que no produzca una tarjeta gigante cuando solo hay un elemento.