repeat() y minmax(): describir pistas sin enumerarlas
La notación de repetición con patrones, minmax con sus restricciones reales, fit-content como tope de crecimiento y los valores intrínsecos aplicados a pistas.
Enumerar doce pistas a mano funciona hasta que cambia el diseño. repeat() y minmax() son las dos funciones que convierten una lista de números en una descripción de intenciones: cuántas veces se repite un patrón, y entre qué límites puede moverse una pista. Con ellas y con los valores intrínsecos que ya conoces, la definición de una rejilla deja de ser una tabla de medidas y pasa a ser un conjunto de reglas.
- Usar
repeat()con un número, con un patrón de varias pistas y combinado con pistas sueltas. - Enunciar las restricciones de
minmax()y las combinaciones inválidas. - Aplicar
min-content,max-content,autoyfit-content()a pistas. - Explicar la diferencia entre una pista
autoy una pista1fr.
repeat con un número
La forma básica repite una definición de pista un número entero de veces:
/* Estas dos son idénticas */
.a { grid-template-columns: 1fr 1fr 1fr 1fr; }
.b { grid-template-columns: repeat(4, 1fr); }
El primer argumento es el número de repeticiones y el segundo es la lista de pistas a repetir. Esa lista puede tener más de una pista, lo que permite describir patrones:
/* Seis pistas: estrecha, ancha, estrecha, ancha, estrecha, ancha */
.patron { grid-template-columns: repeat(3, 8rem 1fr); }
Y repeat() puede convivir con pistas sueltas antes y después:
/* Barra lateral, cuatro columnas iguales, y barra de acciones */
.panel {
display: grid;
grid-template-columns: 16rem repeat(4, 1fr) 4rem;
gap: 1rem;
}
También funciona en filas, y funciona igual con grid-auto-rows y grid-auto-columns, aunque ahí el uso más habitual es una lista de valores que se cicla en lugar de una repetición explícita.
repeat(4, [col] 1fr) genera cuatro líneas llamadas col, y entonces puedes referirte a la tercera con grid-column: col 3. Es una de las funcionalidades más potentes y menos usadas de grid, y la verás con detalle en el nivel siguiente.
minmax y sus restricciones
minmax(min, max) define una pista que nunca baja del primer valor ni sube del segundo. Es el equivalente de min-inline-size y max-inline-size a nivel de pista.
/* Nunca menos de 12rem, nunca más de 24rem, y flexible en medio */
.lateral { grid-template-columns: minmax(12rem, 24rem) 1fr; }
Las restricciones son tres y conviene tenerlas presentes porque los errores de sintaxis en grid se descartan en silencio junto con toda la declaración.
Una unidad flexible no puede ir en el mínimo. minmax(1fr, 300px) es inválido. La razón, como ya viste, es que el valor de un fr depende del espacio libre y el espacio libre depende de los mínimos ya resueltos.
Si el mínimo es mayor que el máximo, gana el mínimo. minmax(300px, 100px) no es un error: el máximo se ignora y la pista mide 300px. Es coherente con cómo min-inline-size gana a max-inline-size.
Los porcentajes en el eje de bloque son problemáticos. minmax(20%, auto) en grid-template-rows depende de que el contenedor tenga una altura determinable. Si no la tiene, el porcentaje se trata como auto, con lo que tu mínimo desaparece sin aviso.
Los valores intrínsecos como pistas
Las palabras clave del nivel 15 funcionan como tamaño de pista y son la clave de las rejillas que se adaptan al contenido.
min-content da una pista tan estrecha como el contenido más ancho permita partirse. Útil para columnas de iconos o de etiquetas cortas.
max-content da una pista tan ancha como el contenido más largo sin partir. Útil para columnas de fechas, importes o identificadores que no deben romperse.
auto como tamaño de pista es un caso especial que merece explicación. Como máximo, se comporta como max-content. Como mínimo, se comporta como el mínimo automático del contenido. Y además, a diferencia de max-content, una pista auto sí puede estirarse para absorber espacio libre cuando justify-content o align-content valen normal o stretch, que son los valores por defecto.
fit-content(L) es la pista que crece con el contenido hasta un tope. Equivale a minmax(auto, max-content) recortado por L.
/* Etiqueta ajustada, valor flexible */
.definiciones { grid-template-columns: max-content 1fr; }
/* Columna que crece con el contenido pero nunca más de 20rem */
.tabla { grid-template-columns: fit-content(20rem) 1fr auto; }
Con una sola pista y espacio de sobra, auto y 1fr parecen iguales porque ambos se estiran. Con varias pistas se ven distintos: 1fr 1fr reparte a partes iguales ignorando el contenido, mientras que auto auto da a cada pista su max-content y luego reparte el sobrante entre ellas a partes iguales. Con contenidos desiguales, auto auto produce pistas desiguales y 1fr 1fr no.
Combinaciones que resuelven problemas reales
Estas cuatro combinaciones cubren la mayoría de las necesidades y merece la pena reconocerlas de un vistazo.
Barra lateral flexible con topes. El lateral se adapta al viewport pero nunca deja de ser usable ni se come la pantalla.
.con-lateral {
display: grid;
grid-template-columns: minmax(14rem, 20rem) 1fr;
gap: 2rem;
}
Contenido centrado con márgenes que absorben. El contenido tiene un ancho máximo y los laterales se llevan el resto, sin margin: auto ni contenedores extra.
.pagina {
display: grid;
grid-template-columns: 1fr min(65ch, 100%) 1fr;
}
.pagina > * { grid-column: 2; }
.pagina > .ancho-completo { grid-column: 1 / -1; }
Este patrón es especialmente bueno: los hijos van a la columna central por defecto, y cualquiera que necesite romper a ancho completo solo tiene que declarar 1 / -1. Sin anidar contenedores y sin márgenes negativos.
Tabla de definiciones. Etiquetas que ocupan lo suyo y valores que se llevan el resto, alineados en columna aunque las etiquetas tengan longitudes distintas.
.ficha {
display: grid;
grid-template-columns: max-content 1fr;
gap: 0.5rem 1.5rem;
}
Filas de altura mínima que crecen. Cada fila mide al menos 4rem y crece si su contenido lo pide.
.calendario {
display: grid;
grid-auto-rows: minmax(4rem, auto);
}
Esa última combinación, minmax(altura, auto), es probablemente la más útil de todo grid: garantiza un mínimo sin impedir el crecimiento, y sustituye a min-block-size en el elemento, que en grid no siempre se comporta como uno espera por culpa del estiramiento.
Hay una diferencia de mantenimiento entre 1fr 1fr 1fr 1fr y repeat(4, 1fr) que no es de brevedad. La primera es un dato, cuatro medidas que alguien decidió; la segunda es una regla, un patrón con un parámetro. Cuando el diseño pasa de cuatro a seis columnas, la primera versión hay que reescribirla y la segunda hay que ajustarla en un carácter. Cuando alguien decide que la rejilla se genere desde una variable, la primera versión no sirve y la segunda acepta repeat(var(--columnas), 1fr) sin más. Y cuando llega auto-fill, la primera versión no tiene equivalente posible y la segunda sí. El mismo argumento vale para minmax() frente a un punto de ruptura: un minmax(14rem, 20rem) describe un rango de comportamiento aceptable, mientras que una media query que cambia 14rem por 20rem a los 60rem de viewport describe una transición concreta que solo es correcta en el contexto donde la mediste. La generalización que conviene llevarse de todo este nivel es que en CSS moderno casi siempre existe la opción de escribir el dato o de escribir la regla que lo genera, y que la segunda cuesta más de pensar la primera vez y menos en cada una de las siguientes. Los sistemas de diseño que envejecen mal están llenos de datos; los que envejecen bien están llenos de reglas con pocos parámetros.