Subgrid: Heredando la cuadrícula matemática de los padres a los hijos.

Publicado: 11/03/2026 Por: Juan Felipe Orozco Cortés
📚 Contenido de la guía

CSS Subgrid: Heredando la Matemática

Tus tarjetas pueden tener grids internos, pero sus títulos, precios o botones casi nunca quedan alineados entre sí. Hoy en Tu Código Cotidiano vamos a resolver esta fractura visual. Entenderemos por qué Subgrid existe: para que los hijos hereden la lógica matemática del padre y se alineen de verdad.

🎨 CSS Moderno 📐 Grid Layout ✨ Subgrid 📏 UI/UX
Comparación visual entre un grid anidado normal desalineado y un subgrid perfectamente alineado con la retícula de fondo
Figura 1. A la izquierda, un grid anidado tradicional ignora el sistema espacial. A la derecha, un elemento con subgrid adopta la cuadrícula del padre, permitiendo una alineación matemática exacta de sus piezas internas.

¿Qué vamos a resolver hoy?

Evitaremos que esta guía sea una simple lista aburrida de propiedades CSS abstractas. Vamos a abordar un dolor muy real en el desarrollo de interfaces. Si alineas un listado de componentes y te das cuenta de que el botón de la tarjeta A no se alinea con el botón de la tarjeta B porque los textos tienen distinto tamaño, estás sufriendo la "fractura de los grids anidados".

🎯 La Promesa

Al final del artículo, sabrás cómo usar subgrid para que los hijos hereden el layout base, logrando alineaciones perfectas sin usar "márgenes mágicos" ni alturas fijas.

👤 Perfil del Lector

Desarrollador Web o Diseñador UI que ya sabe usar CSS Grid para armar estructuras básicas, pero sufre creando layouts consistentes a múltiples niveles.

⚠️ El Problema

Crear display: grid dentro de otro grid genera un "universo de bolsillo". La lógica del padre no penetra en el hijo, fracturando el diseño del sistema.

El problema que sí duele: Tarjetas desalineadas

Piensa en el patrón de diseño más común de la web: un listado de tarjetas (servicios, productos, artículos). Tú aplicas un display: grid en el contenedor principal para ordenar las tarjetas en columnas. Hasta ahí, todo es perfecto.

Pero luego, cada tarjeta necesita su propia cuadrícula interna para acomodar su imagen, título, precio y botón de acción. Como señala la documentación oficial (MDN y web.dev), las pistas de un grid padre solo sirven para posicionar a los hijos directos. Al declarar un nuevo grid dentro de la tarjeta, la estructura matemática del layout general se pierde por completo.

Aquí es donde nace la fractura: un título ligeramente más largo en una tarjeta empuja el precio hacia abajo, desalineándolo de la tarjeta vecina. Tu interfaz pierde el ritmo visual y empieza a verse descuidada, porque las piezas internas ya no comparten la misma lógica espacial.

Ilustración de tres tarjetas desalineadas debido al uso de grids anidados tradicionales sin subgrid.
Figura 2. El caos sutil: La tarjeta central tiene un título más largo que empuja su contenido hacia abajo. La tarjeta derecha tiene contenido corto, dejando su botón flotando. Ninguna respeta las líneas guía del contenedor padre.

Lo más frustrante de este problema es que tu código CSS no tiene errores de sintaxis. Si inspeccionas este comportamiento, verás el patrón clásico del grid anidado que todos hemos escrito mil veces:

card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}
.card {
  display: grid;
  <span style="color: #ea580c; font-weight: bold;">grid-template-rows: auto auto 1fr auto;</span> <span style="color: #64748b; font-style: italic;">/* Título, Meta, Info, Botón */</span>
  gap: 1rem;
}

En el ejemplo anterior, la propiedad grid-template-rows dentro de .card calcula el espacio basándose únicamente en el contenido de esa tarjeta específica, ignorando por completo lo que miden los títulos de sus hermanas. Para solucionar esto, no necesitamos trucos con JavaScript ni asignar alturas fijas en píxeles; necesitamos heredar la cuadrícula del padre.

Mini TL;DR:

El grid anidado clásico aísla la estructura. La función subgrid permite que un grid interno comparta las medidas de las pistas (tracks), las plantillas y los nombres de línea con su ancestro, fusionando los componentes en un solo sistema matemático.

Qué es CSS Subgrid (sin tecnicismos aburridos)

Para entender subgrid, primero hay que entender lo que no es: no es una nueva propiedad mágica de CSS, ni es un valor de display (no escribes display: subgrid).

subgrid es simplemente un valor que le puedes pasar a las propiedades que ya conoces: grid-template-columns y grid-template-rows.

Cuando a un elemento hijo (que ya es display: grid) le pones el valor subgrid en sus columnas o filas, le estás dando una instrucción muy clara al navegador: "Oye, no inventes nuevas pistas matemáticas para mí. Mírate en el espejo de tu padre y adopta exactamente la porción del grid principal sobre la que estoy sentado".

Diagrama de un módulo hijo que adopta exactamente las mismas líneas verticales y horizontales de la cuadrícula padre que lo envuelve.
Figura 3. El hijo iluminado: En lugar de crear pistas nuevas y ciegas, un elemento con subgrid se vuelve "transparente" a las líneas del ancestro que atraviesan la porción de espacio que le fue asignada.

Fíjate bien en la imagen superior. El módulo hijo azul oscuro no está definiendo que sus columnas miden "100px" ni "1fr". Simplemente se acopla a la retícula global que existe en el fondo. Si mañana cambias el tamaño de las columnas en el contenedor principal superior (el padre), este hijo se actualizará y ajustará automáticamente.

Esta es la magia de adoptar la "porción del padre". Rompe el aislamiento. Ahora puedes tener componentes muy complejos, anidados unos dentro de otros a varios niveles de profundidad, y todos pueden responder a una única fuente de verdad matemática definida en la etiqueta <main> o <body> de tu aplicación web.

Lo mejor de dos mundos

Lo fascinante de subgrid es que puedes decidir qué heredar. Puedes heredar solo las columnas (para que los anchos coincidan perfectamente con tus hermanas), pero declarar tus propias filas autónomas. O viceversa. O ambas. Tú tienes el control.

Por qué Subgrid era la pieza que faltaba en CSS

Antes de que existiera subgrid, teníamos un problema grave de "amnesia espacial" en el navegador. Imagina que defines una cuadrícula maestra de 12 columnas para tu página. Colocas un artículo que ocupa desde la columna 2 hasta la 8. Perfecto.

Pero, ¿qué pasaba si querías que los elementos dentro de ese artículo se alinearan con las columnas 3, 4 y 5 de la página principal? No podías. Al anidar un nuevo display: grid, el contenedor hijo "olvidaba" por completo las líneas, los tamaños de las pistas (tracks) y los nombres de línea de su padre.

Los desarrolladores teníamos que recurrir a trucos: usar porcentajes, adivinar anchos fijos o usar variables CSS complejas para intentar imitar la cuadrícula exterior. Y todo ese castillo de naipes se derrumbaba en el momento en que el contenido dinámico (un texto más largo o una imagen de otro tamaño) entraba en juego.

Comparación entre grid anidado tradicional y subgrid alineado.
Figura 4. A la izquierda, el grid anidado rompe la alineación. A la derecha, subgrid hace que los hijos compartan la misma retícula del padre.

Como puedes ver en la comparativa, subgrid existe por una razón de peso: es la única forma nativa en CSS de mantener la integridad estructural en layouts anidados sin tener que duplicar valores ni pelear con anchos en porcentajes.

Al compartir los tamaños de los tracks (las pistas por donde fluye el contenido), una tarjeta anidada ya no tiene que preocuparse por medir el ancho de sus columnas; simplemente le dice al navegador: "Hazme coincidir con las columnas de mi contenedor principal".

Basta de teoría. Veamos cómo se escribe esto en el mundo real.

La sintaxis: Cómo heredar la retícula paso a paso

Implementar esta técnica es sorprendentemente sencillo. Lo primero que debes recordar es que el elemento hijo sigue necesitando ser un grid. No puedes usar subgrid en un bloque normal; primero debes declararlo con display: grid.

Una vez que el hijo es un grid, en lugar de inventar tamaños para tus columnas o filas (como harías con 1fr 1fr o 200px auto), simplemente usas la palabra clave subgrid.

La genialidad de esta sintaxis es que es direccional. Puedes heredar solo las columnas, solo las filas, o ambas dimensiones al mismo tiempo, dependiendo de lo que necesite tu diseño.

Tres paneles demostrando subgrid. El primero hereda solo columnas, el segundo hereda solo filas, y el tercero hereda ambas dimensiones simultáneamente.
Figura 5. Flexibilidad dimensional. Izquierda: heredamos solo el eje vertical (columnas). Centro: heredamos solo el eje horizontal (filas). Derecha: heredamos ambos ejes para anclarnos a la retícula completa del padre.

Pasar esta lógica visual al código es directo y limpio. Tienes tres opciones principales dependiendo de tu objetivo de diseño:

/* ESCENARIO 1: Heredar SOLO columnas */
/* Útil cuando quieres que las tarjetas midan lo mismo de ancho, pero definan sus propias alturas internas */
.hijo-columnas {
  display: grid;
  grid-template-columns: subgrid;
  grid-template-rows: auto 1fr auto; /* Filas locales */
}

/* ESCENARIO 2: Heredar SOLO filas */
/* Útil para listas o tablas donde franjas horizontales deben cruzarse de lado a lado */
.hijo-filas {
  display: grid;
  grid-template-columns: 1fr 2fr; /* Columnas locales */
  grid-template-rows: subgrid;
}

/* ESCENARIO 3: Heredar TODO el layout */
/* Fusión total con la matemática del contenedor padre */
.hijo-absoluto {
  display: grid;
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;
}
Pro Tip: ¿Qué pasa con el "gap"?

Cuando usas subgrid, tu elemento hijo hereda automáticamente el gap del padre para mantener la geometría perfecta. Sin embargo, si lo necesitas, puedes sobreescribir ese espaciado declarando un nuevo gap, row-gap o column-gap dentro del hijo.

Más allá de las medidas: Heredando la estructura lógica

Hasta ahora hemos hablado de heredar anchos (como 200px o 1fr), pero la verdadera potencia de subgrid para construir arquitecturas sólidas va un paso más allá: también hereda los nombres de las líneas del grid padre.

Si eres de los que nombran las líneas en CSS Grid (por ejemplo, [content-start] o [sidebar-end]), sabes lo útil que es para posicionar elementos sin tener que contar columnas matemáticamente. Cuando un componente hijo declara subgrid, todas esas líneas nombradas por el padre "atraviesan" la frontera del hijo y quedan disponibles para ser usadas internamente.

Esto significa que puedes tener un componente anidado a tres niveles de profundidad que, internamente, posiciona un elemento diciéndole: "Alineate con la línea [content-start] del layout maestro", y funcionará a la perfección.

Diagrama que muestra cómo las líneas nombradas de una cuadrícula padre atraviesan visualmente un componente hijo, permitiendo que sus elementos internos se alineen a ellas.
Figura 6. Continuidad semántica: El componente hijo (borde azul) no necesita calcular márgenes internos. Simplemente usa los nombres de línea [content-start] y [content-end] que fueron definidos en la cuadrícula maestra del ancestro.

Mira este escenario sumamente común en arquitecturas modernas: tienes un contenedor principal (layout) que define nombres para organizar el contenido centrado y los sangrados (bleed) laterales. Si insertas un componente de ancho completo, puedes hacer que sus hijos internos respeten ese contenido centrado heredando las líneas:

/* 1. El Layout Maestro (El Padre) define las líneas nombradas */
.layout-maestro {
  display: grid;
  grid-template-columns: 
    [full-start] 1fr 
    [content-start] minmax(0, 800px) 
    [content-end] 1fr 
    [full-end];
}

/* 2. El Componente Hijo ocupa todo el ancho */
.componente-banda {
  grid-column: full-start / full-end;
  background-color: #f1f5f9;
  
  /* Se vuelve un grid y HEREDA la retícula del maestro */
  display: grid;
  grid-template-columns: subgrid;
}

/* 3. El Nieto usa los nombres de línea del Abuelo */
.banda-contenido-interno {
  /* ¡Magia! Este componente conoce las líneas [content-start] y [content-end] */
  grid-column: content-start / content-end;
}

Al aplicar grid-template-columns: subgrid, el .componente-banda elimina su frontera espacial. Su contenido interno (.banda-contenido-interno) ahora es capaz de "ver" y anclarse a las pistas nombradas que definió .layout-maestro. Esto es un nivel de desacoplamiento brutal: tu componente ya no necesita saber cuánto mide la pantalla, solo necesita saber en qué líneas debe posicionarse.

El caso de uso estrella: Tarjetas con anatomía perfecta

Es hora de arreglar el desastre que vimos al principio de esta guía. Tenemos tres tarjetas. Una tiene un título muy largo, otra tiene poco texto, y los botones de acción están flotando en diferentes alturas, arruinando el ritmo visual de nuestra interfaz.

¿Cómo logramos que el botón de la tarjeta 1 se alinee perfectamente con el botón de la tarjeta 2, incluso si sus textos tienen longitudes abismalmente distintas? La respuesta es usar subgrid en el eje de las filas (grid-template-rows). Al hacer esto, las tarjetas dejarán de calcular sus alturas de forma aislada y se verán obligadas a sincronizarse a través del contenedor padre.

Tres tarjetas alineadas horizontalmente. Líneas guía cian atraviesan las tres tarjetas sincronizando las alturas de sus títulos, descripciones y botones.
Figura 7. Sincronización perfecta: Al usar subgrid en las filas, la tarjeta del centro (con el título más largo) obliga a la fila completa del contenedor padre a crecer, y automáticamente las tarjetas 1 y 3 ajustan sus espacios internos para mantener los botones alineados al fondo.

Para lograr este efecto, tenemos que hacer un pequeño cambio de mentalidad. El contenedor padre (el que envuelve a todas las tarjetas) ya no solo manejará las columnas, también debe administrar las filas de los elementos internos.

Si nuestra tarjeta tiene 4 elementos (Título, Metadata, Párrafo, Botón), le diremos a la tarjeta que debe abarcar 4 filas de su padre usando grid-row: span 4;. Luego, activamos subgrid para que esos 4 elementos internos se encajen en esas 4 filas prestadas. Mira el código solucionado:

/* 1. EL CONTENEDOR PADRE */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Definimos explícitamente el tamaño de las 4 filas que compartiremos */
  grid-template-rows: auto auto 1fr auto; 
  gap: 1.5rem;
}

/* 2. LA TARJETA HIJA */
.card {
  display: grid;
  /* La tarjeta debe estirarse para ocupar 4 filas del contenedor padre */
  grid-row: span 4;
  
  /* LA MAGIA: Heredamos la estructura de las filas del padre */
  grid-template-rows: subgrid;
  
  /* Nota: el 'gap' en las filas ahora se hereda del padre automáticamente */
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  background: #ffffff;
  padding: 1.25rem;
}

/* 3. ELEMENTOS INTERNOS (Opcional, pero buena práctica) */
.card h3, .card span, .card p, .card button {
  /* Se colocarán automáticamente en cada una de las 4 filas heredadas */
  margin: 0;
}

Estás viendo solo el 60% del contenido. ¡Únete a la Membresía Premium! para acceder al contenido completo.

← Volver a Guías

Comentarios y Valoraciones

No hay comentarios aún. ¡Sé el primero en opinar!