Nombrar líneas y los nombres implícitos
Poner nombres a las líneas de la rejilla, repetir nombres con índice, y la bidireccionalidad que casi nadie conoce: un área genera líneas -start y -end, y unas líneas -start y -end generan un área.
Colocar por número funciona hasta que cambias la rejilla y todos los números se desplazan uno. Nombrar líneas resuelve eso y algo más: crea un vocabulario compartido entre la definición de la rejilla y los elementos. Y hay una simetría que la documentación menciona de pasada y que resulta ser una de las funcionalidades más elegantes de grid: los nombres de área y los nombres de línea se generan mutuamente.
- Nombrar líneas en
grid-template-columnsy usarlas al colocar elementos. - Dar varios nombres a una misma línea y saber para qué sirve.
- Usar
repeat()con nombres y referirse a la repetición N por índice. - Explicar la generación mutua entre nombres de área y nombres de línea.
Nombrar líneas
Los nombres van entre corchetes, en la posición donde está la línea, dentro de la definición de pistas:
.pagina {
display: grid;
grid-template-columns:
[borde-inicio] 2rem
[contenido-inicio] 1fr
[contenido-fin] 2rem
[borde-fin];
}
.destacado { grid-column: borde-inicio / borde-fin; }
.normal { grid-column: contenido-inicio / contenido-fin; }
Los corchetes no son pistas: son etiquetas para las líneas que separan las pistas. En el ejemplo hay tres pistas y cuatro líneas, cada una con su nombre.
Una línea puede tener varios nombres, y eso es más útil de lo que parece:
grid-template-columns:
[lateral-inicio] 16rem
[lateral-fin principal-inicio] 1fr
[principal-fin];
La línea del medio se llama a la vez lateral-fin y principal-inicio. Cada elemento usa el nombre que tenga sentido desde su punto de vista, y si algún día metes un gap o una pista entre medias, los dos nombres se separan sin que ningún elemento cambie.
[contenido-inicio] sin comillas. Con comillas se convierte en una cadena y la declaración se descarta. Es distinto de grid-template-areas, donde cada fila sí va entre comillas. Mezclar las dos sintaxis es un error frecuente al empezar.
Nombres repetidos y el índice
Dentro de repeat() puedes nombrar líneas, y como la repetición genera varias líneas con el mismo nombre, aparece una sintaxis con índice:
.rejilla {
display: grid;
grid-template-columns: repeat(12, [col] 1fr);
}
/* Desde la tercera línea llamada col, cinco pistas */
.pieza { grid-column: col 3 / span 5; }
col 3 significa “la tercera línea llamada col”. El índice también admite valores negativos, contando desde el final: col -2 es la penúltima línea llamada col.
Esto reproduce la ergonomía de los sistemas de rejilla de doce columnas de la generación anterior, sin sus clases ni su aritmética:
.rejilla-12 {
display: grid;
grid-template-columns: repeat(12, [col] minmax(0, 1fr));
gap: 1.5rem;
}
.media { grid-column: col 1 / span 6; }
.tercio { grid-column: col 7 / span 4; }
También puedes nombrar la línea de cierre de la repetición añadiendo un nombre al final del patrón: repeat(12, [col-inicio] 1fr [col-fin]) genera dos familias de nombres, útil cuando quieres referirte al final de una pista concreta.
La generación mutua
Aquí está la parte que sorprende. Los nombres de área y los nombres de línea no son dos sistemas separados: cada uno genera el otro.
Un área genera cuatro líneas. Si defines un área llamada principal en grid-template-areas, el motor crea automáticamente las líneas principal-start y principal-end en los dos ejes. Puedes usarlas aunque nunca las escribieras:
.pagina {
display: grid;
grid-template-areas:
"cabecera cabecera"
"lateral principal";
}
/* Este elemento no usa el área, usa las líneas que el área generó */
.superpuesto {
grid-column: principal-start / principal-end;
grid-row: cabecera-start / principal-end;
}
Y unas líneas generan un área. Si nombras líneas con los sufijos -start y -end usando la misma raíz, el motor crea un área implícita con esa raíz. Puedes colocarte en ella con grid-area:
.pagina {
display: grid;
grid-template-columns: [principal-start] 1fr 1fr [principal-end];
grid-template-rows: [principal-start] auto auto [principal-end];
}
/* Este elemento usa un área que nunca declaraste como área */
.cubrir { grid-area: principal; }
Los sufijos son literalmente -start y -end en inglés, no traducibles: forman parte de la sintaxis. La raíz sí puede estar en el idioma que quieras.
Esta bidireccionalidad permite un patrón muy limpio: defines la rejilla con líneas nombradas, que es lo más flexible, y los elementos que ocupan un rectángulo completo se colocan con grid-area y un solo nombre, que es lo más legible.
.tarjeta {
display: grid;
grid-template-columns: [medio-start] 1fr [medio-end];
grid-template-rows: auto [medio-start] 1fr [medio-end] auto;
}
.tarjeta > .cuerpo { grid-area: medio; }
grid-area y sus cuatro valores
grid-area es la abreviatura de las cuatro propiedades de colocación, en un orden que no es el de las manecillas del reloj y que conviene memorizar:
/* row-start / column-start / row-end / column-end */
.pieza { grid-area: 2 / 1 / 4 / 3; }
El orden es inicio de fila, inicio de columna, fin de fila, fin de columna. Es el mismo orden que en inset y en margin de cuatro valores: arriba, izquierda, abajo, derecha, empezando por el eje de bloque. Con un solo valor, grid-area: principal, se interpreta como un nombre de área.
Los valores omitidos toman auto, con una regla: si el valor omitido corresponde a una línea de fin y el de inicio es un nombre personalizado, el fin toma ese mismo nombre; en cualquier otro caso, auto.
.a { grid-area: 2 / 3; } /* fila 2, columna 3, ambos con span 1 */
.b { grid-area: principal; } /* el área completa */
.c { grid-column: principal; } /* solo el eje en línea del área */
Ese último caso es útil: puedes usar el nombre de un área para colocarte solo en uno de sus ejes.
CSS no tiene funciones, no tiene variables de verdad hasta las custom properties, no tiene abstracción de ningún tipo. Lo único que tiene, transversalmente, es la capacidad de dar nombres a cosas y referirse a ellas por ese nombre: nombres de clase, de custom property, de área, de línea, de capa en cascada, de container, de animación, de fuente, de vista en las view transitions. Toda la indirección disponible en el lenguaje pasa por ahí. Y una vez lo ves así, el criterio para decidir entre grid-column: 3 y grid-column: contenido-inicio deja de ser una cuestión de gusto: la primera acopla el elemento a la estructura actual de la rejilla, la segunda lo acopla a una intención que sobrevive a los cambios de estructura. Es exactamente la diferencia entre una constante mágica y una constante nombrada en cualquier otro lenguaje, con el agravante de que en CSS no hay compilador que te ayude a encontrar todos los usos cuando el número cambia. La bidireccionalidad entre áreas y líneas es la mejor prueba de que el grupo de trabajo entendió esto: no se limitó a añadir nombres, se aseguró de que los dos sistemas de nombres se generaran mutuamente para que nunca tuvieras que mantener los dos a mano. Cuando revises CSS ajeno, un buen indicador de calidad es contar cuántos números literales hay en las declaraciones de colocación. Cuantos más, más frágil es el layout, independientemente de lo moderna que sea la técnica.