- CSS Grid ha sido ampliamente compatible en los principales navegadores desde marzo de 2017, pero
grid-template-areas todavía se usa menos, aunque permite expresar el layout visualmente dentro del CSS sin calcular números de línea
grid-template-areas funciona colocando nombres de áreas como cadenas y vinculándolos con grid-area en los elementos hijos; los nombres repetidos deben formar obligatoriamente un área rectangular
- Las líneas de grid con nombre consisten en asignar nombres a las líneas, como
content-start / content-end, y el patrón *-start y *-end permite que el navegador los use como áreas implícitas
- En casos como tarjetas invertidas, headers responsivos, layouts editoriales, publicaciones estilo Threads, tarjetas superpuestas y layouts condicionales con
:has(), se pueden gestionar variantes de distribución cambiando solo las cadenas de áreas del contenedor padre
- Chrome, Safari y Firefox ofrecen DevTools para áreas de Grid, y Firefox resulta especialmente útil por mostrar nombres de áreas y ofrecer autocompletado de nombres de línea posibles al editar
grid-area
Hacer que los layouts sean más legibles con grid-template-areas
- En CSS Grid, una forma común de posicionar elementos ha sido indicar directamente números de línea, como
grid-column: 1 / 3
- Los números de línea no se ven hasta revisarlos en DevTools, y en layouts con columnas y filas es difícil calcular mentalmente los números correctos
grid-template-areas asigna nombres a cada celda, así que el propio CSS se ve como un mapa del layout
.page {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas: "item1 item2";
gap: 1rem;
}
.item-1 {
grid-area: item1;
}
.item-2 {
grid-area: item2;
}
- Los elementos hijos se mapean a áreas con nombre usando
grid-area
- En el ejemplo de tarjetas, una definición como
"featured featured article" permite que el área featured ocupe 2 columnas y article ocupe 1
Sintaxis y reglas que hay que respetar sí o sí
grid-template-areas acepta una o más cadenas de áreas
- Una sola cadena crea un layout unidimensional con solo columnas
- Varias cadenas forman un layout multidimensional con filas y columnas
- Cuando se usan varias cadenas, escribirlas en líneas separadas hace que el layout sea más fácil de leer
.element {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-areas:
"aside main"
"footer footer";
}
- Cada cadena representa una fila del grid, y puede pensarse como una tabla
- Las áreas definidas con el mismo nombre deben ser rectangulares dentro del código
/* invalid */
.layout {
grid-template-areas:
"header header"
"sidebar main"
"header footer";
}
/* valid */
.layout {
grid-template-areas:
"header header"
"sidebar main"
"sidebar footer";
}
- Todas las filas deben tener la misma cantidad de tokens de área, y aunque un área no se use, la celda en sí debe definirse
- Las celdas vacías pueden representarse con un punto o con varios puntos
.element {
grid-template-areas:
"aside main"
"... footer";
}
- El punto es un null cell token de la especificación de CSS Grid, y representa una celda vacía del grid
Relación entre líneas de grid con nombre y áreas
- En CSS Grid siempre hay una línea más que la cantidad de columnas
- Si hay 3 columnas, se crean 4 líneas de grid
- Las líneas de grid con nombre consisten en asignar nombres únicos a las líneas en lugar de usar solo números
.layout {
grid-template-columns:
[full-start] 1fr
[content-start] 2fr
[content-end] 1fr [full-end];
}
.item {
grid-column: content-start / content-end;
}
- Aunque pongas nombre a las líneas, las líneas numéricas siguen pudiéndose usar
- El tamaño de pista (track size) se refiere al tamaño de una columna o fila, y valores como
1fr 1fr son tamaños de pista
- En las líneas con nombre, se nombran las líneas alrededor de las pistas
.layout {
display: grid;
grid-template-columns:
[aside-start] 200px [aside-end main-start] 1fr [main-end];
}
- Una misma línea puede compartir varios nombres; en el ejemplo de arriba,
aside-end y main-start son la misma línea
- Si defines nombres como
aside-start y aside-end, el navegador puede permitir usos como grid-column: aside mediante nombres de línea implícitos
- No hace falta nombrar todas las líneas; se pueden nombrar selectivamente solo las importantes
- Al posicionar elementos, se pueden mezclar números y nombres, como en
grid-column: 1 / content-end
Gestionar variantes de layout con las cadenas de áreas del contenedor padre
- Al usar
grid-template-areas, puedes mantener los nombres grid-area de los hijos y cambiar todo el layout modificando solo las cadenas de áreas del contenedor padre
.aside {
grid-area: aside;
}
.main {
grid-area: main;
}
.footer {
grid-area: footer;
}
- Si mantienes los mismos nombres
aside, main y footer, basta con cambiar la cadena de grid-template-areas para actualizar automáticamente toda la distribución
- El control del layout queda centralizado en la definición de áreas del padre, lo que facilita los ajustes
Invertir la orientación de una tarjeta
- Con Flexbox, es fácil invertir la dirección de una tarjeta con
flex-direction: row-reverse
- En CSS Grid, si usas números de línea, al cambiar la dirección tienes que modificar tanto la definición de columnas como los valores
grid-column de cada hijo
- Con áreas con nombre, basta con asignar imagen y contenido a áreas y luego cambiar solo el orden de esas áreas en el contenedor padre
.card {
display: grid;
grid-template-columns: 150px 1fr;
grid-template-areas: "thumb content";
}
.card__thumb {
grid-area: thumb;
}
.card__content {
grid-area: content;
}
.card--flip {
grid-template-columns: 1fr 150px;
grid-template-areas: "content thumb";
}
- El mismo layout también puede expresarse con la propiedad abreviada
grid-template
.card--flip {
grid-template: "content image" / 1fr 150px;
}
- La propiedad abreviada es opcional, y también es válido preferir la versión larga por ser más legible
Layout de header responsivo
- Un header con logo, navegación y acciones puede comenzar con 3 columnas del mismo tamaño
- Si usas números de línea, tienes que asignar
grid-column a .logo, .nav y .actions por separado
- Si usas nombres de área, puedes mapear cada hijo a
logo, nav y actions, y luego cambiar solo grid-template-areas del padre según el viewport
.header {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas: "logo nav actions";
}
.logo {
grid-area: logo;
}
.nav {
grid-area: nav;
}
.actions {
grid-area: actions;
}
- En tamaños pequeños, el logo y las acciones pueden ir en la primera fila y la navegación puede ocupar todo el ancho
.header {
grid-template-areas:
"logo logo actions"
"nav nav nav";
}
- A partir de
380px, el logo puede quedar a la izquierda y la navegación y acciones a la derecha
@media (min-width: 380px) {
.header {
grid-template-areas:
"logo nav nav"
"logo actions actions";
}
.nav {
justify-self: end;
}
}
- A partir de
900px, puede volver a una distribución en una sola fila
@media (min-width: 900px) {
.header {
grid-template-areas: "logo nav actions";
}
}
- Las cadenas de áreas funcionan como un mapeo que muestra directamente la distribución de la UI dentro del CSS
Ejemplo de layout editorial
- Una sección con título, texto e imagen puede cambiar fácilmente su distribución según el tamaño del viewport usando
grid-template-areas
.section {
display: grid;
grid-template-areas:
". title title"
"thumb content content";
gap: 1rem;
}
- El punto a la izquierda del título representa espacio vacío y es un null cell token
- En el ejemplo de una sección estilo time.com, se usan las áreas
feature, secondary y most-read, junto con columnas vacías a ambos lados
.featured-section {
display: grid;
grid-template-areas:
". feature most-read ."
". secondary most-read .";
grid-template-columns: 1fr minmax(auto, 57.313rem) minmax(12rem, 18.75rem) 1fr;
grid-template-rows: minmax(auto, 25rem) 1fr;
}
- Las columnas vacías de ambos lados suelen servir como separación horizontal
- En la versión responsiva, en pantallas pequeñas se apilan verticalmente
feature, secondary y most-read, y a partir de 500px y 900px se cambian las definiciones de columnas y áreas
grid-template-rows puede sustituirse por la definición de áreas, así que no es estrictamente necesario
Componente de publicación estilo Threads
- Al revisar el CSS de Threads app by Meta, se puede ver un caso de uso de CSS Grid en un componente de publicación
- El ejemplo original posiciona elementos con
grid-template-columns, grid-template-rows y números de línea
.postBody {
grid-column-start: 2;
grid-row-start: 2;
grid-row-end: span 3;
}
- Varias variantes de publicación pueden expresarse más fácilmente con
grid-template-areas
.post {
grid-template-areas:
"avatar header"
"avatar body"
". body"
". footer";
}
.post--reply {
grid-template-rows: 40px max-content max-content;
grid-template-areas:
"avatar header"
"body body"
"body body"
"footer footer";
}
.post--nested {
grid-template-areas:
"avatar header"
"avatar body"
"line body"
"footer footer";
}
- Solo con mirar las cadenas de áreas se pueden distinguir la variante base, la respuesta y la publicación anidada
Elementos superpuestos y nombres de área
- En
grid-template-areas, los nombres repetidos deben formar rectángulos, así que repetir el mismo nombre con una forma no rectangular no es válido
.layout {
display: grid;
grid-template-columns: 1fr 1fr fr;
grid-template-areas:
"card tag tag"
"title title card";
}
- En el ejemplo de arriba,
card no forma un rectángulo, así que es invalid
- En tarjetas superpuestas, se pueden definir nombres nuevos como
thumb-1 y thumb-2, y luego usarlos en grid-column y grid-row
.card {
display: grid;
grid-template-columns: auto auto 1fr;
grid-template-rows: auto auto;
grid-template-areas:
"thumb-1 tag"
"title thumb-2";
}
.thumb {
grid-column: thumb-1 / thumb-2;
grid-row: thumb-1 / thumb-2;
}
- La etiqueta y el título pueden colocarse con
grid-area y alinearse con align-self y justify-self
- Si hace falta, hay que gestionar el orden de apilamiento de los hijos, aunque en el ejemplo basta con el orden del código fuente
- Este ejemplo de superposición está inspirado en la página Oddbird’s Cascading Layouts
:has() y layouts condicionales
- Al combinar el selector CSS
:has() con áreas de Grid, se puede cambiar el layout según exista o no cierto elemento
- Se pueden aplicar definiciones de áreas distintas dentro de
<figure> según haya o no figcaption
figure {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas: "img img img";
gap: 0.5rem;
}
img {
grid-area: img;
}
figcaption {
grid-area: caption;
}
.card:has(figcaption) {
grid-template-areas:
"img img caption"
"img img .";
}
Compatibilidad con direcciones LTR/RTL en entornos multilingües
- CSS Grid ajusta el layout según si la página está en dirección LTR o RTL
- Las áreas de grid con nombre también siguen la dirección de la página, así que el layout se invierte en una configuración RTL
- Para escribir layouts RTL, puede consultarse la guía RTL Styling 101
Diferencias en el soporte de DevTools
- Chrome, Safari y Firefox ofrecen DevTools para áreas de Grid
- Chrome
- Coloca los nombres de las áreas en la esquina superior izquierda, lo que puede hacer que se vean superpuestos
- La superposición de color puede cambiar la forma en que se percibe el diseño
- Safari
- El contorno rosa ayuda a distinguir claramente los elementos
- Permite ver los nombres de línea
- La forma de mostrar los nombres de línea todavía podría mejorar, por ejemplo apilándolos mejor
- Firefox
- Los nombres de área se ven más claros que en Chrome y Safari
- Ofrece una lista de autocompletado al escribir nombres personalizados como
*-start y *-end
- Al editar
grid-area de un elemento hijo, muestra la lista completa de nombres de línea disponibles
Material de referencia
1 comentarios
Opiniones en Hacker News
La demo animada me pareció bastante interesante, pero fue una lástima enterarme de que esa animación no estaba hecha con CSS.
Después de aprender Flexbox pensé “con esto es suficiente” y no profundicé en Grid. Parece haber razones para preferir Grid [0], pero en general nunca necesité hacer algo que solo se pudiera hacer con Grid, y para tablas de datos uso un
<table>real.[0] https://css-tricks.com/css-grid-replace-flexbox/
Solo he usado Grid para cosas como galerías de imágenes responsivas como https://labs.jensimmons.com/2016/examples/image-gallery-grid... o tarjetas responsivas como https://every-layout.dev/demos/grid-cards/.
grid-template-columnsvale la pena aprenderlo ygrid-gapes práctico. Fuera de eso, siento que Flexbox se encarga de casi todo.Dicho eso,
grid-template-areastodavía me resulta ambiguo. El artículo argumenta que facilita ajustar layouts por breakpoint o cuando “un compañero del equipo necesita cambiar el layout”, pero quizá simplemente no soy el público objetivo.Puedes usar ambos según lo necesites y, combinados, se vuelven una herramienta de layout muy potente.
https://www.youtube.com/watch?v=MWWcZzossc8
Espera, ¿
1/3no es una fracción sino un rango de 1 a 3? No entiendo por qué eligieron esa sintaxis. En programación hay muchas sintaxis razonables y conocidas para representar rangos, como1..3.Creo que muchos de los problemas que los programadores tienen con CSS vienen de ese malentendido.
!importantno significa “no importante”, sino “¡importante!”.Nunca llegué a dominar bien ni Grid ni Flexbox. La última estrategia de layout que más o menos manejé bien fue float. Este artículo me dio confianza para probar CSS Grid la próxima vez que diseñe un layout, y además está muy bien hecho.
Hay muchos buenos artículos, pero con leer estos dos de CSS-Tricks me alcanzó:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
https://css-tricks.com/snippets/css/complete-guide-grid/
Además de los artículos de CSS-Tricks ya mencionados, recomiendo la guía de Flexbox de MDN[1] y la referencia “CSS flexible box layout”[2]. Me ayudaron a entender mejor los conceptos detrás de Flexbox, sus propiedades y cómo funcionan realmente las propiedades abreviadas.
[1]: https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layou...
[2]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexibl...
Dicho eso, Flexbox sigue siendo más bien un layout unidimensional con posibilidad de salto de línea, así que el truco está en anidar y apilar. Grid tiene plantillas y sus hijos directos ocupan áreas predefinidas, por lo que es más estático que Flexbox, y tiene la limitación de no afectar a los elementos anidados internos. Aun así, parece que subgrid cambiará esa parte.
Recursos relacionados:
Grid Garden https://cssgridgarden.com
Flexbox Froggy https://flexboxfroggy.com
Me gustaría que hubiera una versión más básica, “antes de la introducción”, que este documento. Me trabé desde la parte introductoria y no pude avanzar. En especial, en la parte que dice “para ubicar elementos hijos dentro de Grid, hay que especificar el número de línea de cada elemento con
grid-column”, no entiendo qué significa número de línea ahí.Seguí adelante pensando que lo entendería por contexto, pero enseguida volví a trabarme con expresiones como
1 / 3y1 / 4.|a||b|, las dos líneas del medio en realidad se cuentan como una sola, así que hay 3 en total.Por eso
1/3no es una fracción, sino un rango de columnas, y significa “empieza en la línea 1 y termina en la línea 3”.El nombre “número de línea” no es muy bueno, pero en la práctica son los bordes de las columnas. Así que
1/3va desde el borde 1, es decir, el extremo izquierdo, hasta el borde 3, y ocupa las 2 columnas completas.Para CSS Grid recomiendo muchísimo Jen Simmons Mondrian with auto flow. En https://labs.jensimmons.com/2017/01-011.html prueba presionar
CyDy cambiar el tamaño de la ventana. También hay un video de YouTube para verlo junto con eso: https://www.youtube.com/watch?v=qNtJ5p3h2A4Es realmente genial.
Lo que todavía quiero entender de auto flow es cómo detectar y rellenar huecos. Cuando hay objetos de tamaños variados al azar, ¿cómo se hace para que auto flow no deje espacios vacíos? ¿O se puede detectar un hueco y agregar algo?
Espero que no sea una pregunta tonta, pero ¿por qué definieron la sintaxis con una barra, como
1/2,3/4? ¿No sería más natural algo como1-2, de la columna 1 a la 2, o1->2?1--1,1->-1o1/-1?En CSS los valores ya se separan con espacios y, considerando además la intuición que solemos tener cuando aparece un guion, lo siguiente es mucho mejor:
grid-column: 4 somegridarea / 6;grid-column: span 3 / 6;grid-column: span somegridarea / span someothergridarea;Es mucho más claro que escribirlo así:
grid-column: 4 somegridarea-6;grid-column: span 3-6;grid-column: span 3->6;grid-column: span somegridarea-span someothergridarea;grid-column: span somegridarea->span someothergridarea;Me encantan este tipo de artículos de blog interactivos. Para Grid, recomiendo mucho probar directamente las grid areas en herramientas como https://grid.layoutit.com/.
Llevo años planificando layouts con Grid en ese sitio, y ajustar los espacios se vuelve mucho más fácil.
Quizá esta sea la primera vez que realmente entiendo CSS Grid. La visualización de números ayudó muchísimo, y es un artículo que voy a consultar seguido en adelante.
Me gustan CSS Grid y el concepto de áreas, pero sigo pensando que la parte más difícil es la gestión responsive, especialmente entre tamaños móviles y de escritorio. Según qué elemento de la UI deba estar abierto o deba ocupar toda la pantalla, muchas veces hay que actualizar
grid-template-areay los tamaños de filas/columnas con JavaScript.Todavía no encontré un mundo donde
minmaxocalclo resuelvan, y ojalá alguien sepa la respuesta.var(--foo), en lugar de valores fijos.Así, desde JavaScript solo actualizas el valor de esa variable, y Grid refleja ese valor.
display: noneen ese tamaño.Un ejemplo muy simple: https://codepen.io/trescenzi/pen/vYqpjvL
:has()o subgrid, aunque no tengo mucha experiencia directa.